PageSourceSearch

https://www.thionvilletouristamt.de/app/dist/pays-thionvillois/add…/code/es-modules/Core/Series/Point.js

js thionvilletouristamt.de collected 2026-09-29 17:15:35 UTC 48,484 bytes, 1,314 lines download raw bytes

1/* *
2 *
3 *  (c) 2010-2024 Torstein Honsi
4 *
5 *  License: www.highcharts.com/license
6 *
7 *  !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
8 *
9 * */
10'use strict';
11import AST from '../Renderer/HTML/AST.js';
12import A from '../Animation/AnimationUtilities.js';
13const { animObject } = A;
14import D from '../Defaults.js';
15const { defaultOptions } = D;
16import F from '../Templating.js';
17const { format } = F;
18import U from '../Utilities.js';
19const { addEvent, crisp, erase, extend, fireEvent, getNestedProperty, isArray, isFunction, isNumber, isObject, merge, pick, syncTimeout, removeEvent, uniqueKey } = U;
20/* eslint-disable no-invalid-this, valid-jsdoc */
21/* *
22 *
23 *  Class
24 *
25 * */
26/**
27 * The Point object. The point objects are generated from the `series.data`
28 * configuration objects or raw numbers. They can be accessed from the
29 * `Series.points` array. Other ways to instantiate points are through {@link
30 * Highcharts.Series#addPoint} or {@link Highcharts.Series#setData}.
31 *
32 * @class
33 * @name Highcharts.Point
34 */
35class Point {
36    /**
37     * For categorized axes this property holds the category name for the
38     * point. For other axes it holds the X value.
39     *
40     * @name Highcharts.Point#category
41     * @type {number|string}
42     */
43    /**
44     * The name of the point. The name can be given as the first position of the
45     * point configuration array, or as a `name` property in the configuration:
46     *
47     * @example
48     * // Array config
49     * data: [
50     *     ['John', 1],
51     *     ['Jane', 2]
52     * ]
53     *
54     * // Object config
55     * data: [{
56     *        name: 'John',
57     *        y: 1
58     * }, {
59     *     name: 'Jane',
60     *     y: 2
61     * }]
62     *
63     * @name Highcharts.Point#name
64     * @type {string}
65     */
66    /**
67     * The point's name if it is defined, or its category in case of a category,
68     * otherwise the x value. Convenient for tooltip and data label formatting.
69     *
70     * @name Highcharts.Point#key
71     * @type {number|string}
72     */
73    /**
74     * The point's options as applied in the initial configuration, or
75     * extended through `Point.update`.
76     *
77     * In TypeScript you have to extend `PointOptionsObject` via an
78     * additional interface to allow custom data options:
79     *
80     * ```
81     * declare interface PointOptionsObject {
82     *     customProperty: string;
83     * }
84     * ```
85     *
86     * @name Highcharts.Point#options
87     * @type {Highcharts.PointOptionsObject}
88     */
89    /**
90     * The percentage for points in a stacked series, pies or gauges.
91     *
92     * @name Highcharts.Point#percentage
93     * @type {number|undefined}
94     */
95    /**
96     * The series object associated with the point.
97     *
98     * @name Highcharts.Point#series
99     * @type {Highcharts.Series}
100     */
101    /**
102     * The attributes of the rendered SVG shape like in `column` or `pie`
103     * series.
104     *
105     * @readonly
106     * @name Highcharts.Point#shapeArgs
107     * @type {Readonly<Highcharts.SVGAttributes>|undefined}
108     */
109    /**
110     * The total of values in either a stack for stacked series, or a pie in a
111     * pie series.
112     *
113     * @name Highcharts.Point#total
114     * @type {number|undefined}
115     */
116    /**
117     * For certain series types, like pie charts, where individual points can
118     * be shown or hidden.
119     *
120     * @name Highcharts.Point#visible
121     * @type {boolean}
122     * @default true
123     */
124    /* *
125     *
126     *  Functions
127     *
128     * */
129    /**
130     * Animate SVG elements associated with the point.
131     *
132     * @private
133     * @function Highcharts.Point#animateBeforeDestroy
134     */
135    animateBeforeDestroy() {
136        const point = this, animateParams = { x: point.startXPos, opacity: 0 }, graphicalProps = point.getGraphicalProps();
137        graphicalProps.singular.forEach(function (prop) {
138            const isDataLabel = prop === 'dataLabel';
139            point[prop] = point[prop].animate(isDataLabel ? {
140                x: point[prop].startXPos,
141                y: point[prop].startYPos,
142                opacity: 0
143            } : animateParams);
144        });
145        graphicalProps.plural.forEach(function (plural) {
146            point[plural].forEach(function (item) {
147                if (item.element) {
148                    item.animate(extend({ x: point.startXPos }, (item.startYPos ? {
149                        x: item.startXPos,
150                        y: item.startYPos
151                    } : {})));
152                }
153            });
154        });
155    }
156    /**
157     * Apply the options containing the x and y data and possible some extra
158     * properties. Called on point init or from point.update.
159     *
160     * @private
161     * @function Highcharts.Point#applyOptions
162     *
163     * @param {Highcharts.PointOptionsType} options
164     *        The point options as defined in series.data.
165     *
166     * @param {number} [x]
167     *        Optionally, the x value.
168     *
169     * @return {Highcharts.Point}
170     *         The Point instance.
171     */
172    applyOptions(options, x) {
173        const point = this, series = point.series, pointValKey = series.options.pointV
173alKey || series.pointValKey;
174        options = Point.prototype.optionsToObject.call(this, options);
175        // Copy options directly to point
176        extend(point, options);
177        point.options = point.options ?
178            extend(point.options, options) :
179            options;
180        // Since options are copied into the Point instance, some accidental
181        // options must be shielded (#5681)
182        if (options.group) {
183            delete point.group;
184        }
185        if (options.dataLabels) {
186            delete point.dataLabels;
187        }
188        /**
189         * The y value of the point.
190         * @name Highcharts.Point#y
191         * @type {number|undefined}
192         */
193        // For higher dimension series types. For instance, for ranges, point.y
194        // is mapped to point.low.
195        if (pointValKey) {
196            point.y = Point.prototype.getNestedProperty.call(point, pointValKey);
197        }
198        // The point is initially selected by options (#5777)
199        if (point.selected) {
200            point.state = 'select';
201        }
202        /**
203         * The x value of the point.
204         * @name Highcharts.Point#x
205         * @type {number}
206         */
207        // If no x is set by now, get auto incremented value. All points must
208        // have an x value, however the y value can be null to create a gap in
209        // the series
210        if ('name' in point &&
211            typeof x === 'undefined' &&
212            series.xAxis &&
213            series.xAxis.hasNames) {
214            point.x = series.xAxis.nameToX(point);
215        }
216        if (typeof point.x === 'undefined' && series) {
217            point.x = x ?? series.autoIncrement();
218        }
219        else if (isNumber(options.x) && series.options.relativeXValue) {
220            point.x = series.autoIncrement(options.x);
221            // If x is a string, try to parse it to a datetime
222        }
223        else if (typeof point.x === 'string') {
224            x ?? (x = series.chart.time.parse(point.x));
225            if (isNumber(x)) {
226                point.x = x;
227            }
228        }
229        point.isNull = this.isValid && !this.isValid();
230        point.formatPrefix = point.isNull ? 'null' : 'point'; // #9233, #10874
231        return point;
232    }
233    /**
234     * Destroy a point to clear memory. Its reference still stays in
235     * `series.data`.
236     *
237     * @private
238     * @function Highcharts.Point#destroy
239     */
240    destroy() {
241        if (!this.destroyed) {
242            const point = this, series = point.series, chart = series.chart, dataSorting = series.options.dataSorting, hoverPoints = chart.hoverPoints, globalAnimation = point.series.chart.renderer.globalAnimation, animation = animObject(globalAnimation);
243            /**
244             * Allow to call after animation.
245             * @private
246             */
247            const destroyPoint = () => {
248                // Remove all events and elements
249                if (point.graphic ||
250                    point.graphics ||
251                    point.dataLabel ||
252                    point.dataLabels) {
253                    removeEvent(point);
254                    point.destroyElements();
255                }
256                for (const prop in point) { // eslint-disable-line guard-for-in
257                    delete point[prop];
258                }
259            };
260            if (point.legendItem) {
261                // Pies have legend items
262                chart.legend.destroyItem(point);
263            }
264            if (hoverPoints) {
265                point.setState();
266                erase(hoverPoints, point);
267                if (!hoverPoints.length) {
268                    chart.hoverPoints = null;
269                }
270            }
271            if (point === chart.hoverPoint) {
272                point.onMouseOut();
273            }
274            // Remove properties after animation
275            if (!dataSorting || !dataSorting.enabled) {
276                destroyPoint();
277            }
278            else {
279                this.animateBeforeDestroy();
280                syncTimeout(destroyPoint, animation.duration);
281            }
282            chart.pointCount--;
283        }
284        this.destroyed = true;
285    }
286    /**
287     * Destroy SVG elements associated with the point.
288     *
289     * @private
290     * @function Highcharts.Point#destroyElements
291     * @param {Highcharts.Dictionary<number>} [kinds]
292     */
293    destroyElements(kinds) {
294        const point = this, props = point.getGraphicalProps(kinds);
295        props.singular.forEach(function (prop) {
296            point[prop] = point[prop].destroy();
297        });
298        props.plural.forEach(function (plural) {
299            point[plural].forEach(function (item) {
300                if (item && item.element) {
301                    item.destroy();
302                }
303            });
304            delete point[plural];
305        });
306    }
307    /**
308     * Fire an event on the Point object.
309     *
310     * @private
311     * @function Highcharts.Point#firePointEvent
312     *
313     * @param {string} eventType
314     *        Type of the event.
315     *
316     * @param {Highcharts.Dictionary<any>|Event} [eventArgs]
317     *        Additional event arguments.
318     *
319     * @param {Highcharts.EventCallbackFunction<Highcharts.Point>|Function} [defaultFunction]
320     *        Default event handler.
321     *
322     * @emits Highcharts.Point#event:*
323     */
324    firePointEvent(eventType, eventArgs, defaultFunction) {
325        const point = this, series = this.series, seriesOptions = series.options;
326        // Load event handlers on demand to save time on mouseover/out
327        point.manageEvent(eventType);
328        // Add default handler if in selection mode
329        if (eventType === 'click' && seriesOptions.allowPointSelect) {
330            defaultFunction = function (event) {
331                // Control key is for Windows, meta (= Cmd key) for Mac, Shift
332                // for Opera.
333                if (!point.destroyed && point.select) { // #2911, #19075
334                    point.select(null, event.ctrlKey || event.metaKey || event.shiftKey);
335                }
336            };
337        }
338        fireEvent(point, eventType, eventArgs, defaultFunction);
339    }
340    /**
341     * Get the CSS class names for individual points. Used internally where the
342     * returned value is set on every point.
343     *
344     * @function Highcharts.Point#getClassName
345     *
346     * @return {string}
347     *         The class names.
348     */
349    getClassName() {
350        const point = this;
351        return 'highcharts-point' +
352            (point.selected ? ' highcharts-point-select' : '') +
353            (point.negative ? ' highcharts-negative' : '') +
354            (point.isNull ? ' highcharts-null-point' : '') +
355            (typeof point.colorIndex !== 'undefined' ?
356                ' highcharts-color-' + point.colorIndex : '') +
357            (point.options.className ? ' ' + point.options.className : '') +
358            (point.zone && point.zone.className ? ' ' +
359                point.zone.className.replace('highcharts-negative', '') : '');
360    }
361    /**
362     * Get props of all existing graphical point elements.
363     *
364     * @private
365     * @function Highcharts.Point#getGraphicalProps
366     */
367    getGraphicalProps(kinds) {
368        const point = this, props = [], graphicalProps = { singular: [], plural: [] };
369        let prop, i;
370        kinds = kinds || { graphic: 1, dataLabel: 1 };
371        if (kinds.graphic) {
372            props.push('graphic', 'connector' // Used by dumbbell
373            );
374        }
375        if (kinds.dataLabel) {
376            props.push('dataLabel', 'dataLabelPath', 'dataLabelUpper');
377        }
378        i = props.length;
379        while (i--) {
380            prop = props[i];
381            if (point[prop]) {
382                graphicalProps.singular.push(prop);
383            }
384        }
385        [
386            'graphic',
387            'dataLabel'
388        ].forEach(function (prop) {
389            const plural = prop + 's';
390            if (kinds[prop] && point[plural]) {
391                graphicalProps.plural.push(plural);
392            }
393        });
394        return graphicalProps;
395    }
396    /**
397     * Returns the value of the point property for a given value.
398     * @private
399     */
400    getNestedProperty(key) {
401        if (!key) {
402            return;
403        }
404        if (key.indexOf('custom.') === 0) {
405            return getNestedProperty(key, this.options);
406        }
407        return this[key];
408    }
409    /**
410     * In a series with `zones`, return the zone that the point belongs to.
411     *
412     * @function Highcharts.Point#getZone
413     *
414     * @return {Highcharts.SeriesZonesOptionsObject}
415     *         The zone item.
416     */
417    getZone() {
418        const series = this.series, zones = series.zones, zoneAxis = series.zoneAxis || 'y';
419        let zone, i = 0;
420        zone = zones[i];
421        while (this[zoneAxis] >= zone.value) {
422            zone = zones[++i];
423        }
424        // For resetting or reusing the point (#8100)
425        if (!this.nonZonedColor) {
426            this.nonZonedColor = this.color;
427        }
428        if (zone && zone.color && !this.options.color) {
429            this.color = zone.color;
430        }
431        else {
432            this.color = this.nonZonedColor;
433        }
434        return zone;
435    }
436    /**
437     * Utility to check if point has new shape type. Used in column series and
438     * all others that are based on column series.
439     * @private
440     */
441    hasNewShapeType() {
442        const point = this;
443        const oldShapeType = point.graphic &&
444            (point.graphic.symbolName || point.graphic.element.nodeName);
445        return oldShapeType !== this.shapeType;
446    }
447    /**
448     * Initialize the point. Called internally based on the `series.data`
449     * option.
450     *
451     * @function Highcharts.Point#init
452     *
453     * @param {Highcharts.Series} series
454     *        The series object containing this point.
455     *
456     * @param {Highcharts.PointOptionsType} options
457     *        The data in either number, array or object format.
458     *
459     * @param {number} [x]
460     *        Optionally, the X value of the point.
461     *
462     * @return {Highcharts.Point}
463     *         The Point instance.
464     *
465     * @emits Highcharts.Point#event:afterInit
466     */
467    constructor(series, options, x) {
468        this.formatPrefix = 'point';
469        this.visible = true;
470        // For tooltip and data label formatting
471        this.point = this;
472        this.series = series;
473        this.applyOptions(options, x);
474        // Add a unique ID to the point if none is assigned
475        this.id ?? (this.id = uniqueKey());
476        this.resolveColor();
477        series.chart.pointCount++;
478        fireEvent(this, 'afterInit');
479    }
480    /**
481     * Determine if point is valid.
482     * @private
483     * @function Highcharts.Point#isValid
484     */
485    isValid() {
486        return ((isNumber(this.x) ||
487            this.x instanceof Date) &&
488            isNumber(this.y));
489    }
490    /**
491     * Transform number or array configs into objects. Also called for object
492     * configs. Used internally to unify the different configuration formats for
493     * points. For example, a simple number `10` in a line series will be
494     * transformed to `{ y: 10 }`, and an array config like `[1, 10]` in a
495     * scatter series will be transformed to `{ x: 1, y: 10 }`.
496     *
497     * @function Highcharts.Point#optionsToObject
498     *
499     * @param {Highcharts.PointOptionsType} options
500     * Series data options.
501     *
502     * @return {Highcharts.Dictionary<*>}
503     * Transformed point options.
504     */
505    optionsToObject(options) {
506        const series = this.series, keys = series.options.keys, pointArrayMap = keys || series.pointArrayMap || ['y'], valueCount = pointArrayMap.length;
507        let ret = {}, firstItemType, i = 0, j = 0;
508        if (isNumber(options) || options === null) {
509            ret[pointArrayMap[0]] = options;
510        }
511        else if (isArray(options)) {
512            // With leading x value
513            if (!keys && options.length > valueCount) {
514                firstItemType = typeof options[0];
515                if (firstItemType === 'string') {
516                    if (series.xAxis?.dateTime) {
517                        ret.x = series.chart.time.parse(options[0]);
518                    }
519                    else {
520                        ret.name = options[0];
521                    }
522                }
523                else if (firstItemType === 'number') {
524                    ret.x = options[0];
525                }
526                i++;
527            }
528            while (j < valueCount) {
529                // Skip undefined positions for keys
530                if (!keys || typeof options[i] !== 'undefined') {
531                    if (pointArrayMap[j].indexOf('.') > 0) {
532                        // Handle nested keys, e.g. ['color.pattern.image']
533                        // Avoid function call unless necessary.
534                        Point.prototype.setNestedProperty(ret, options[i], pointArrayMap[j]);
535                    }
536                    else {
537                        ret[pointArrayMap[j]] = options[i];
538                    }
539                }
540                i++;
541                j++;
542            }
543        }
544        else if (typeof options === 'object') {
545            ret = options;
546            // This is the fastest way to detect if there are individual point
547            // dataLabels that need to be considered in drawDataLabels. These
548            // can only occur in object configs.
549            if (options.dataLabels) {
550                // Override the prototype function to always return true,
551                // regardless of whether data labels are enabled series-wide
552                series.hasDataLabels = () => true;
553            }
554            // Same approach as above for markers
555            if (options.marker) {
556                series._hasPointMarkers = true;
557            }
558        }
559        return ret;
560    }
561    /**
562     * Get the pixel position of the point relative to the plot area.
563     * @function Highcharts.Point#pos
564     *
565     * @sample highcharts/point/position
566     *         Get point's position in pixels.
567     *
568     * @param {boolean} chartCoordinates
569     * If true, the returned position is relative to the full chart area.
570     * If false, it is relative to the plot area determined by the axes.
571     *
572     * @param {number|undefined} plotY
573     * A custom plot y position to be computed. Used internally for some
574     * series types that have multiple `y` positions, like area range (low
575     * and high values).
576     *
577     * @return {Array<number>|undefined}
578     * Coordinates of the point if the point exists.
579     */
580    pos(chartCoordinates, plotY = this.plotY) {
581        if (!this.destroyed) {
582            const { plotX, series } = this, { chart, xAxis, yAxis } = series;
583            let posX = 0, posY = 0;
584            if (isNumber(plotX) && isNumber(plotY)) {
585                if (chartCoordinates) {
586                    posX = xAxis ? xAxis.pos : chart.plotLeft;
587                    posY = yAxis ? yAxis.pos : chart.plotTop;
588                }
589                return chart.inverted && xAxis && yAxis ?
590                    [yAxis.len - plotY + posY, xAxis.len - plotX + posX] :
591                    [plotX + posX, plotY + posY];
592            }
593        }
594    }
595    /**
596     * @private
597     * @function Highcharts.Point#resolveColor
598     */
599    resolveColor() {
600        const series = this.series, optionsChart = series.chart.options.chart, styledMode = series.chart.styledMode;
601        let color, colors, colorCount = optionsChart.colorCount, colorIndex;
602        // Remove points nonZonedColor for later recalculation
603        delete this.nonZonedColor;
604        if (series.options.colorByPoint) {
605            if (!styledMode) {
606                colors = series.options.colors || series.chart.options.colors;
607                color = colors[series.colorCounter];
608                colorCount = colors.length;
609            }
610            colorIndex = series.colorCounter;
611            series.colorCounter++;
612            // Loop back to zero
613            if (series.colorCounter === colorCount) {
614                series.colorCounter = 0;
615            }
616        }
617        else {
618            if (!styledMode) {
619                color = series.color;
620            }
621            colorIndex = series.colorIndex;
622        }
623        /**
624         * The point's current color index, used in styled mode instead of
625         * `color`. The color index is inserted in class names used for styling.
626         *
627         * @name Highcharts.Point#colorIndex
628         * @type {number|undefined}
629         */
630        this.colorIndex = pick(this.options.colorIndex, colorIndex);
631        /**
632         * The point's current color.
633         *
634         * @name Highcharts.Point#color
635         * @type {Highcharts.ColorString|Highcharts.GradientColorObject|Highcharts.PatternObject|undefined}
636         */
637        this.color = pick(this.options.color, color);
638    }
639    /**
640     * Set a value in an object, on the property defined by key. The key
641     * supports nested properties using dot notation. The function modifies the
642     * input object and does not make a copy.
643     *
644     * @function Highcharts.Point#setNestedProperty<T>
645     *
646     * @param {T} object
647     *        The object to set the value on.
648     *
649     * @param {*} value
650     *        The value to set.
651     *
652     * @param {string} key
653     *        Key to the property to set.
654     *
655     * @return {T}
656     *         The modified object.
657     */
658    setNestedProperty(object, value, key) {
659        const nestedKeys = key.split('.');
660        nestedKeys.reduce(function (result, key, i, arr) {
661            const isLastKey = arr.length - 1 === i;
662            result[key] = (isLastKey ?
663                value :
664                isObject(result[key], true) ?
665                    result[key] :
666                    {});
667            return result[key];
668        }, object);
669        return object;
670    }
671    shouldDraw() {
672        return !this.isNull;
673    }
674    /**
675     * Extendable method for formatting each point's tooltip line.
676     *
677     * @function Highcharts.Point#tooltipFormatter
678     *
679     * @param {string} pointFormat
680     *        The point format.
681     *
682     * @return {string}
683     *         A string to be concatenated in to the common tooltip text.
684     */
685    tooltipFormatter(pointFormat) {
686        // Insert options for valueDecimals, valuePrefix, and valueSuffix
687        const { chart, pointArrayMap = ['y'], tooltipOptions } = this.series, { valueDecimals = '', valuePrefix = '', valueSuffix = '' } = tooltipOptions;
688        // Replace default point style with class name
689        if (chart.styledMode) {
690            pointFormat = chart.tooltip?.styledModeFormat(pointFormat) ||
691                pointFormat;
692        }
693        // Loop over the point array map and replace unformatted values with
694        // sprintf formatting markup
695        pointArrayMap.forEach((key) => {
696            key = '{point.' + key; // Without the closing bracket
697            if (valuePrefix || valueSuffix) {
698                pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), valuePrefix + key + '}' + valueSuffix);
699            }
700            pointFormat = pointFormat.replace(RegExp(key + '}', 'g'), key + ':,.' + valueDecimals + 'f}');
701        });
702        return format(pointFormat, this, chart);
703    }
704    /**
705     * Update point with new options (typically x/y data) and optionally redraw
706     * the series.
707     *
708     * @sample highcharts/members/point-update-column/
709     *         Update column value
710     * @sample highcharts/members/point-update-pie/
711     *         Update pie slice
712     * @sample maps/members/point-update/
713     *         Update map area value in Highmaps
714     *
715     * @function Highcharts.Point#update
716     *
717     * @param {Highcharts.PointOptionsType} options
718     *        The point options. Point options are handled as described under
719     *        the `series.type.data` item for each series type. For example
720     *        for a line series, if options is a single number, the point will
721     *        be given that number as the marin y value. If it is an array, it
722     *        will be interpreted as x and y values respectively. If it is an
723     *        object, advanced options are applied.
724     *
725     * @param {boolean} [redraw=true]
726     *        Whether to redraw the chart after the point is updated. If doing
727     *        more operations on the chart, it is best practice to set
728     *        `redraw` to false and call `chart.redraw()` after.
729     *
730     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=true]
731     *        Whether to apply animation, and optionally animation
732     *        configuration.
733     *
734     * @emits Highcharts.Point#event:update
735     */
736    update(options, redraw, animation, runEvent) {
737        const point = this, series = point.series, graphic = point.graphic, chart = series.chart, seriesOptions = series.options;
738        let i;
739        redraw = pick(redraw, true);
740        /**
741         * @private
742         */
743        function update() {
744            point.applyOptions(options);
745            // Update visuals, #4146
746            // Handle mock graphic elements for a11y, #12718
747            const hasMockGraphic = graphic && point.hasMockGraphic;
748            const shouldDestroyGraphic = point.y === null ?
749                !hasMockGraphic :
750                hasMockGraphic;
751            if (graphic && shouldDestroyGraphic) {
752                point.graphic = graphic.destroy();
753                delete point.hasMockGraphic;
754            }
755            if (isObject(options, true)) {
756                // Destroy so we can get new elements
757                if (graphic && graphic.element) {
758                    // "null" is also a valid symbol
759                    if (options &&
760                        options.marker &&
761                        typeof options.marker.symbol !== 'undefined') {
762                        point.graphic = graphic.destroy();
763                    }
764                }
765                if (options?.dataLabels && point.dataLabel) {
766                    point.dataLabel = point.dataLabel.destroy(); // #2468
767                }
768            }
769            // Record changes in the data table
770            i = point.index;
771            const row = {};
772            for (const key of series.dataColumnKeys()) {
773                row[key] = point[key];
774            }
775            series.dataTable.setRow(row, i);
776            // Record the options to options.data. If the old or the new config
777            // is an object, use point options, otherwise use raw options
778            // (#4701, #4916).
779            seriesOptions.data[i] = (isObject(seriesOptions.data[i], true) ||
780                isObject(options, true)) ?
781                point.options :
782                pick(options, seriesOptions.data[i]);
783            // Redraw
784            series.isDirty = series.isDirtyData = true;
785            if (!series.fixedBox && series.hasCartesianSeries) { // #1906, #2320
786                chart.isDirtyBox = true;
787            }
788            if (seriesOptions.legendType === 'point') { // #1831, #1885
789                chart.isDirtyLegend = true;
790            }
791            if (redraw) {
792                chart.redraw(animation);
793            }
794        }
795        // Fire the event with a default handler of doing the update
796        if (runEvent === false) { // When called from setData
797            update();
798        }
799        else {
800            point.firePointEvent('update', { options: options }, update);
801        }
802    }
803    /**
804     * Remove a point and optionally redraw the series and if necessary the axes
805     *
806     * @sample highcharts/plotoptions/series-point-events-remove/
807     *         Remove point and confirm
808     * @sample highcharts/members/point-remove/
809     *         Remove pie slice
810     * @sample maps/members/point-remove/
811     *         Remove selected points in Highmaps
812     *
813     * @function Highcharts.Point#remove
814     *
815     * @param {boolean} [redraw=true]
816     *        Whether to redraw the chart or wait for an explicit call. When
817     *        doing more operations on the chart, for example running
818     *        `point.remove()` in a loop, it is best practice to set `redraw`
819     *        to false and call `chart.redraw()` after.
820     *
821     * @param {boolean|Partial<Highcharts.AnimationOptionsObject>} [animation=false]
822     *        Whether to apply animation, and optionally animation
823     *        configuration.
824     */
825    remove(redraw, animation) {
826        this.series.removePoint(this.series.data.indexOf(this), redraw, animation);
827    }
828    /**
829     * Toggle the selection status of a point.
830     *
831     * @see Highcharts.Chart#getSelectedPoints
832     *
833     * @sample highcharts/members/point-select/
834     *         Select a point from a button
835     * @sample highcharts/members/point-select-lasso/
836     *         Lasso selection
837     * @sample highcharts/chart/events-selection-points/
838     *         Rectangle selection
839     * @sample maps/series/data-id/
840     *         Select a point in Highmaps
841     *
842     * @function Highcharts.Point#select
843     *
844     * @param {boolean} [selected]
845     * When `true`, the point is selected. When `false`, the point is
846     * unselected. When `null` or `undefined`, the selection state is toggled.
847     *
848     * @param {boolean} [accumulate=false]
849     * When `true`, the selection is added to other selected points.
850     * When `false`, other selected points are deselected. Internally in
851     * Highcharts, when
852     * [allowPointSelect](https://api.highcharts.com/highcharts/plotOptions.series.allowPointSelect)
853     * is `true`, selected points are accumulated on Control, Shift or Cmd
854     * clicking the point.
855     *
856     * @emits Highcharts.Point#event:select
857     * @emits Highcharts.Point#event:unselect
858     */
859    select(selected, accumulate) {
860        const point = this, series = point.series, chart = series.chart;
861        selected = pick(selected, !point.selected);
862        this.selectedStaging = selected;
863        // Fire the event with the default handler
864        point.firePointEvent(selected ? 'select' : 'unselect', { accumulate: accumulate }, function () {
865            /**
866             * Whether the point is selected or not.
867             *
868             * @see Point#select
869             * @see Chart#getSelectedPoints
870             *
871             * @name Highcharts.Point#selected
872             * @type {boolean}
873             */
874            point.selected = point.options.selected = selected;
875            series.options.data[series.data.indexOf(point)] =
876                point.options;
877            point.setState(selected && 'select');
878            // Unselect all other points unless Ctrl or Cmd + click
879            if (!accumulate) {
880                chart.getSelectedPoints().forEach(function (loopPoint) {
881                    const loopSeries = loopPoint.series;
882                    if (loopPoint.selected && loopPoint !== point) {
883                        loopPoint.selected = loopPoint.options.selected =
884                            false;
885                        loopSeries.options.data[loopSeries.data.indexOf(loopPoint)] = loopPoint.options;
886                        // Programmatically selecting a point should restore
887                        // normal state, but when click happened on other
888                        // point, set inactive state to match other points
889                        loopPoint.setState(chart.hoverPoints &&
890                            loopSeries.options.inactiveOtherPoints ?
891                            'inactive' : '');
892                        loopPoint.firePointEvent('unselect');
893                    }
894                });
895            }
896        });
897        delete this.selectedStaging;
898    }
899    /**
900     * Runs on mouse over the point. Called internally from mouse and touch
901     * events.
902     *
903     * @function Highcharts.Point#onMouseOver
904     *
905     * @param {Highcharts.PointerEventObject} [e]
906     *        The event arguments.
907     */
908    onMouseOver(e) {
909        const point = this, series = point.series, { inverted, pointer } = series.chart;
910        if (pointer) {
911            e = e ?
912                pointer.normalize(e) :
913                // In cases where onMouseOver is called directly without an
914                // event
915                pointer.getChartCoordinatesFromPoint(point, inverted);
916            pointer.runPointActions(e, point);
917        }
918    }
919    /**
920     * Runs on mouse out from the point. Called internally from mouse and touch
921     * events.
922     *
923     * @function Highcharts.Point#onMouseOut
924     * @emits Highcharts.Point#event:mouseOut
925     */
926    onMouseOut() {
927        const point = this, chart = point.series.chart;
928        point.firePointEvent('mouseOut');
929        if (!point.series.options.inactiveOtherPoints) {
930            (chart.hoverPoints || []).forEach(function (p) {
931                p.setState();
932            });
933        }
934        chart.hoverPoints = chart.hoverPoint = null;
935    }
936    /**
937     * Manage specific event from the series' and point's options. Only do it on
938     * demand, to save processing time on hovering.
939     *
940     * @private
941     * @function Highcharts.Point#importEvents
942     */
943    manageEvent(eventType) {
944        const point = this, options = merge(point.series.options.point, point.options), userEvent = options.events?.[eventType];
945        if (isFunction(userEvent) &&
946            (!point.hcEvents?.[eventType] ||
947                // Some HC modules, like marker-clusters, draggable-poins etc.
948                // use events in their logic, so we need to be sure, that
949                // callback function is different
950                point.hcEvents?.[eventType]?.map((el) => el.fn)
951                    .indexOf(userEvent) === -1)) {
952            // While updating the existing callback event the old one should be
953            // removed
954            point.importedUserEvent?.();
955            point.importedUserEvent = addEvent(point, eventType, userEvent);
956            if (point.hcEvents) {
957                point.hcEvents[eventType].userEvent = true;
958            }
959        }
960        else if (point.importedUserEvent &&
961            !userEvent &&
962            point.hcEvents?.[eventType] &&
963            point.hcEvents?.[eventType].userEvent) {
964            removeEvent(point, eventType);
965            delete point.hcEvents[eventType];
966            if (!Object.keys(point.hcEvents)) {
967                delete point.importedUserEvent;
968            }
969        }
970    }
971    /**
972     * Set the point's state.
973     *
974     * @function Highcharts.Point#setState
975     *
976     * @param {Highcharts.PointStateValue|""} [state]
977     *        The new state, can be one of `'hover'`, `'select'`, `'inactive'`,
978     *        or `''` (an empty string), `'normal'` or `undefined` to set to
979     *        normal state.
980     * @param {boolean} [move]
981     *        State for animation.
982     *
983     * @emits Highcharts.Point#event:afterSetState
984     */
985    setState(state, move) {
986        const point = this, series = point.series, previousState = point.state, stateOptions = (series.options.states[state || 'normal'] ||
987            {}), markerOptions = (defaultOptions.plotOptions[series.type].marker &&
988            series.options.marker), normalDisabled = (markerOptions && markerOptions.enabled === false), markerStateOptions = ((markerOptions &&
989            markerOptions.states &&
990            markerOptions.states[state || 'normal']) || {}), stateDisabled = markerStateOptions.enabled === false, pointMarker = point.marker || {}, chart = series.chart, hasMarkers = (markerOptions && series.markerAttribs);
991        let halo = series.halo, markerAttribs, pointAttribs, pointAttribsAnimation, stateMarkerGraphic = series.stateMarkerGraphic, newSymbol;
992        state = state || ''; // Empty string
993        if (
994        // Already has this state
995        (state === point.state && !move) ||
996            // Selected points don't respond to hover
997            (point.selected && state !== 'select') ||
998            // Series' state options is disabled
999            (stateOptions.enabled === false) ||
1000            // General point marker's state options is disabled
1001            (state && (stateDisabled ||
1002                (normalDisabled &&
1003                    markerStateOptions.enabled === false))) ||
1004            // Individual point marker's state options is disabled
1005            (state &&
1006                pointMarker.states &&
1007                pointMarker.states[state] &&
1008                pointMarker.states[state].enabled === false) // #1610
1009        ) {
1010            return;
1011        }
1012        point.state = state;
1013        if (hasMarkers) {
1014            markerAttribs = series.markerAttribs(point, state);
1015        }
1016        // Apply hover styles to the existing point
1017        // Prevent from mocked null points (#14966)
1018        if (point.graphic && !point.hasMockGraphic) {
1019            if (previousState) {
1020                point.graphic.removeClass('highcharts-point-' + previousState);
1021            }
1022            if (state) {
1023                point.graphic.addClass('highcharts-point-' + state);
1024            }
1025            if (!chart.styledMode) {
1026                pointAttribs = series.pointAttribs(point, state);
1027                pointAttribsAnimation = pick(chart.options.chart.animation, stateOptions.animation);
1028                const opacity = pointAttribs.opacity;
vendor: 5,779 bytes, lines 1029-1165
1029                // Some inactive points (e.g. slices in pie) should apply
1030                // opacity also for their labels
1031                if (series.options.inactiveOtherPoints && isNumber(opacity)) {
1032                    (point.dataLabels || []).forEach(function (label) {
1033                        if (label &&
1034                            !label.hasClass('highcharts-data-label-hidden')) {
1035                            label.animate({ opacity }, pointAttribsAnimation);
1036                            if (label.connector) {
1037                                label.connector.animate({ opacity }, pointAttribsAnimation);
1038                            }
1039                        }
1040                    });
1041                }
1042                point.graphic.animate(pointAttribs, pointAttribsAnimation);
1043            }
1044            if (markerAttribs) {
1045                point.graphic.animate(markerAttribs, pick(
1046                // Turn off globally:
1047                chart.options.chart.animation, markerStateOptions.animation, markerOptions.animation));
1048            }
1049            // Zooming in from a range with no markers to a range with markers
1050            if (stateMarkerGraphic) {
1051                stateMarkerGraphic.hide();
1052            }
1053        }
1054        else {
1055            // If a graphic is not applied to each point in the normal state,
1056            // create a shared graphic for the hover state
1057            if (state && markerStateOptions) {
1058                newSymbol = pointMarker.symbol || series.symbol;
1059                // If the point has another symbol than the previous one, throw
1060                // away the state marker graphic and force a new one (#1459)
1061                if (stateMarkerGraphic &&
1062                    stateMarkerGraphic.currentSymbol !== newSymbol) {
1063                    stateMarkerGraphic = stateMarkerGraphic.destroy();
1064                }
1065                // Add a new state marker graphic
1066                if (markerAttribs) {
1067                    if (!stateMarkerGraphic) {
1068                        if (newSymbol) {
1069                            series.stateMarkerGraphic = stateMarkerGraphic =
1070                                chart.renderer
1071                                    .symbol(newSymbol, markerAttribs.x, markerAttribs.y, markerAttribs.width, markerAttribs.height, merge(markerOptions, markerStateOptions))
1072                                    .add(series.markerGroup);
1073                            stateMarkerGraphic.currentSymbol = newSymbol;
1074                        }
1075                        // Move the existing graphic
1076                    }
1077                    else {
1078                        stateMarkerGraphic[move ? 'animate' : 'attr']({
1079                            x: markerAttribs.x,
1080                            y: markerAttribs.y
1081                        });
1082                    }
1083                }
1084                if (!chart.styledMode && stateMarkerGraphic &&
1085                    point.state !== 'inactive') {
1086                    stateMarkerGraphic.attr(series.pointAttribs(point, state));
1087                }
1088            }
1089            if (stateMarkerGraphic) {
1090                stateMarkerGraphic[state && point.isInside ? 'show' : 'hide'](); // #2450
1091                stateMarkerGraphic.element.point = point; // #4310
1092                stateMarkerGraphic.addClass(point.getClassName(), true);
1093            }
1094        }
1095        // Show me your halo
1096        const haloOptions = stateOptions.halo;
1097        const markerGraphic = (point.graphic || stateMarkerGraphic);
1098        const markerVisibility = (markerGraphic && markerGraphic.visibility || 'inherit');
1099        if (haloOptions &&
1100            haloOptions.size &&
1101            markerGraphic &&
1102            markerVisibility !== 'hidden' &&
1103            !point.isCluster) {
1104            if (!halo) {
1105                series.halo = halo = chart.renderer.path()
1106                    // #5818, #5903, #6705
1107                    .add(markerGraphic.parentGroup);
1108            }
1109            halo.show()[move ? 'animate' : 'attr']({
1110                d: point.haloPath(haloOptions.size)
1111            });
1112            halo.attr({
1113                'class': 'highcharts-halo highcharts-color-' +
1114                    pick(point.colorIndex, series.colorIndex) +
1115                    (point.className ? ' ' + point.className : ''),
1116                'visibility': markerVisibility,
1117                'zIndex': -1 // #4929, #8276
1118            });
1119            halo.point = point; // #6055
1120            if (!chart.styledMode) {
1121                halo.attr(extend({
1122                    'fill': point.color || series.color,
1123                    'fill-opacity': haloOptions.opacity
1124                }, AST.filterUserAttributes(haloOptions.attributes || {})));
1125            }
1126        }
1127        else if (halo?.point?.haloPath &&
1128            !halo.point.destroyed) {
1129            // Animate back to 0 on the current halo point (#6055)
1130            halo.animate({ d: halo.point.haloPath(0) }, null, 
1131            // Hide after unhovering. The `complete` callback runs in the
1132            // halo's context (#7681).
1133            halo.hide);
1134        }
1135        fireEvent(point, 'afterSetState', { state });
1136    }
1137    /**
1138     * Get the path definition for the halo, which is usually a shadow-like
1139     * circle around the currently hovered point.
1140     *
1141     * @function Highcharts.Point#haloPath
1142     *
1143     * @param {number} size
1144     *        The radius of the circular halo.
1145     *
1146     * @return {Highcharts.SVGPathArray}
1147     *         The path definition.
1148     */
1149    haloPath(size) {
1150        const pos = this.pos();
1151        return pos ? this.series.chart.renderer.symbols.circle(crisp(pos[0], 1) - size, pos[1] - size, size * 2, size * 2) : [];
1152    }
1153}
1154/* *
1155 *
1156 *  Default Export
1157 *
1158 * */
1159export default Point;
1160/* *
1161 *
1162 *  API Declarations
1163 *
1164 * */
1165/**
1166 * Function callback when a series point is clicked. Return false to cancel the
1167 * action.
1168 *
1169 * @callback Highcharts.PointClickCallbackFunction
1170 *
1171 * @param {Highcharts.Point} this
1172 *        The point where the event occurred.
1173 *
1174 * @param {Highcharts.PointClickEventObject} event
1175 *        Event arguments.
1176 */
1177/**
1178 * Common information for a click event on a series point.
1179 *
1180 * @interface Highcharts.PointClickEventObject
1181 * @extends Highcharts.PointerEventObject
1182 */ /**
1183* Clicked point.
1184* @name Highcharts.PointClickEventObject#point
1185* @type {Highcharts.Point}
1186*/
1187/**
1188 * Gets fired when the mouse leaves the area close to the point.
1189 *
1190 * @callback Highcharts.PointMouseOutCallbackFunction
1191 *
1192 * @param {Highcharts.Point} this
1193 *        Point where the event occurred.
1194 *
1195 * @param {global.PointerEvent} event
1196 *        Event that occurred.
1197 */
1198/**
1199 * Gets fired when the mouse enters the area close to the point.
1200 *
1201 * @callback Highcharts.PointMouseOverCallbackFunction
1202 *
1203 * @param {Highcharts.Point} this
1204 *        Point where the event occurred.
1205 *
1206 * @param {global.Event} event
1207 *        Event that occurred.
1208 */
1209/**
1210 * The generic point options for all series.
1211 *
1212 * In TypeScript you have to extend `PointOptionsObject` with an additional
1213 * declaration to allow custom data options:
1214 *
1215 * ```
1216 * declare interface PointOptionsObject {
1217 *     customProperty: string;
1218 * }
1219 * ```
1220 *
1221 * @interface Highcharts.PointOptionsObject
1222 */
1223/**
1224 * Possible option types for a data point. Use `null` to indicate a gap.
1225 *
1226 * @typedef {number|string|Highcharts.PointOptionsObject|Array<(number|string|null)>|null} Highcharts.PointOptionsType
1227 */
1228/**
1229 * Gets fired when the point is removed using the `.remove()` method.
1230 *
1231 * @callback Highcharts.PointRemoveCallbackFunction
1232 *
1233 * @param {Highcharts.Point} this
1234 *        Point where the event occurred.
1235 *
1236 * @param {global.Event} event
1237 *        Event that occurred.
1238 */
1239/**
1240 * Possible key values for the point state options.
1241 *
1242 * @typedef {"hover"|"inactive"|"normal"|"select"} Highcharts.PointStateValue
1243 */
1244/**
1245 * Gets fired when the point is updated programmatically through the `.update()`
1246 * method.
1247 *
1248 * @callback Highcharts.PointUpdateCallbackFunction
1249 *
1250 * @param {Highcharts.Point} this
1251 *        Point where the event occurred.
1252 *
1253 * @param {Highcharts.PointUpdateEventObject} event
1254 *        Event that occurred.
1255 */
1256/**
1257 * Information about the update event.
1258 *
1259 * @interface Highcharts.PointUpdateEventObject
1260 * @extends global.Event
1261 */ /**
1262* Options data of the update event.
1263* @name Highcharts.PointUpdateEventObject#options
1264* @type {Highcharts.PointOptionsType}
1265*/
1266/**
1267 * @interface Highcharts.PointEventsOptionsObject
1268 */ /**
1269* Fires when the point is selected either programmatically or following a click
1270* on the point. One parameter, `event`, is passed to the function. Returning
1271* `false` cancels the operation.
1272* @name Highcharts.PointEventsOptionsObject#select
1273* @type {Highcharts.PointSelectCallbackFunction|undefined}
1274*/ /**
1275* Fires when the point is unselected either programmatically or following a
1276* click on the point. One parameter, `event`, is passed to the function.
1277* Returning `false` cancels the operation.
1278* @name Highcharts.PointEventsOptionsObject#unselect
1279* @type {Highcharts.PointUnselectCallbackFunction|undefined}
1280*/
1281/**
1282 * Information about the select/unselect event.
1283 *
1284 * @interface Highcharts.PointInteractionEventObject
1285 * @extends global.Event
1286 */ /**
1287* @name Highcharts.PointInteractionEventObject#accumulate
1288* @type {boolean}
1289*/
1290/**
1291 * Gets fired when the point is selected either programmatically or following a
1292 * click on the point.
1293 *
1294 * @callback Highcharts.PointSelectCallbackFunction
1295 *
1296 * @param {Highcharts.Point} this
1297 *        Point where the event occurred.
1298 *
1299 * @param {Highcharts.PointInteractionEventObject} event
1300 *        Event that occurred.
1301 */
1302/**
1303 * Fires when the point is unselected either programmatically or following a
1304 * click on the point.
1305 *
1306 * @callback Highcharts.PointUnselectCallbackFunction
1307 *
1308 * @param {Highcharts.Point} this
1309 *        Point where the event occurred.
1310 *
1311 * @param {Highcharts.PointInteractionEventObject} event
1312 *        Event that occurred.
1313 */
1314''; // Keeps doclets above in JS file.

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.