PageSourceSearch

https://www.vendays-montalivet-tourisme.fr/app/dist/vendaysmontali…/Core/Axis/Stacking/StackingAxis.js

js vendays-montalivet-tourisme.fr collected 2026-10-08 16:29:51 UTC 14,607 bytes, 426 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 A from '../../Animation/AnimationUtilities.js';
12const { getDeferredAnimation } = A;
13import Axis from '../Axis.js';
14import SeriesRegistry from '../../Series/SeriesRegistry.js';
15const { series: { prototype: seriesProto } } = SeriesRegistry;
16import StackItem from './StackItem.js';
17import U from '../../Utilities.js';
18const { addEvent, correctFloat, defined, destroyObjectProperties, fireEvent, isNumber, objectEach, pick } = U;
19/* *
20 *
21 *  Functions
22 *
23 * */
24/**
25 * Generate stacks for each series and calculate stacks total values
26 *
27 * @private
28 * @function Highcharts.Chart#getStacks
29 */
30function chartGetStacks() {
31    const chart = this, inverted = chart.inverted;
32    // Reset stacks for each axis
33    chart.axes.forEach((axis) => {
34        if (axis.stacking && axis.stacking.stacks && axis.hasVisibleSeries) {
35            axis.stacking.oldStacks = axis.stacking.stacks;
36        }
37    });
38    chart.series.forEach((series) => {
39        const xAxisOptions = series.xAxis && series.xAxis.options || {};
40        if (series.options.stacking && series.reserveSpace()) {
41            series.stackKey = [
42                series.type,
43                pick(series.options.stack, ''),
44                inverted ? xAxisOptions.top : xAxisOptions.left,
45                inverted ? xAxisOptions.height : xAxisOptions.width
46            ].join(',');
47        }
48    });
49}
50/**
51 * @private
52 */
53function onAxisDestroy() {
54    const stacking = this.stacking;
55    if (stacking) {
56        const stacks = stacking.stacks;
57        // Destroy each stack total
58        objectEach(stacks, (stack, stackKey) => {
59            destroyObjectProperties(stack);
60            delete stacks[stackKey];
61        });
62        stacking.stackTotalGroup?.destroy();
63    }
64}
65/**
66 * @private
67 */
68function onAxisInit() {
69    if (!this.stacking) {
70        this.stacking = new AxisAdditions(this);
71    }
72}
73/**
74 * Get stack indicator, according to it's x-value, to determine points with the
75 * same x-value
76 *
77 * @private
78 * @function Highcharts.Series#getStackIndicator
79 */
80function seriesGetStackIndicator(stackIndicator, x, index, key) {
81    // Update stack indicator, when:
82    // first point in a stack || x changed || stack type (negative vs positive)
83    // changed:
84    if (!defined(stackIndicator) ||
85        stackIndicator.x !== x ||
86        (key && stackIndicator.stackKey !== key)) {
87        stackIndicator = {
88            x: x,
89            index: 0,
90            key,
91            stackKey: key
92        };
93    }
94    else {
95        stackIndicator.index++;
96    }
97    stackIndicator.key = [index, x, stackIndicator.index].join(',');
98    return stackIndicator;
99}
100/**
101 * Iterate over all stacks and compute the absolute values to percent
102 *
103 * @private
104 * @function Highcharts.Series#modifyStacks
105 */
106function seriesModifyStacks() {
107    const series = this, yAxis = series.yAxis, stackKey = series.stackKey || '', stacks = yAxis.stacking.stacks, processedXData = series.getColumn('x', true), stacking = series.options.stacking, stacker = series[stacking + 'Stacker'];
108    let stackIndicator;
109    if (stacker) { // Modifier function exists (Series.percentStacker etc.)
110        [stackKey, '-' + stackKey].forEach((key) => {
111            let i = processedXData.length, x, stackItem, pointExtremes;
112            while (i--) {
113                x = processedXData[i];
114                stackIndicator = series.getStackIndicator(stackIndicator, x, series.index, key);
115                stackItem = stacks[key]?.[x];
116                pointExtremes = stackItem?.points[stackIndicator.key || ''];
117                if (pointExtremes) {
118                    stacker.call(series, pointExtremes, stackItem, i);
119                }
120            }
121        });
122    }
123}
124/**
125 * Modifier function for percent stacks. Blows up the stack to 100%.
126 *
127 * @private
128 * @function Highcharts.Series#percentStacker
129 */
130function seriesPercentStacker(pointExtremes, stack, i) {
131    const totalFactor = stack.total ? 100 / stack.total : 0;
132    // Y bottom value
133    pointExtremes[0] = correctFloat(pointExtremes[0] * totalFactor);
134    // Y value
135    pointExtremes[1] = correctFloat(pointExtremes[1] * totalFactor);
136    this.stackedYData[i] = pointExtremes[1];
137}
138/**
139 * Set grouped points in a stack-like object. When `centerInCategory` is true,
140 * and `stacking` is not enabled, we need a pseudo (horizontal) stack in order
141 * to handle grouping of points within the same category.
142 *
143 * @private
144 * @function Highcharts.Series#setGroupedPoints
145 * @return {void}
146 */
147function seriesSetGroupedPoints(axis) {
148    // Only series types supporting centerInCategory need to do this. That also
149    // applies to resetting (#20221).
150    if (this.is('column') || this.is('columnrange')) {
151        if (this.options.centerInCategory &&
vendor: 5,424 bytes, lines 152-288
152            // With only one series, we don't need to consider centerInCategory
153            this.chart.series.length > 1) {
154            seriesProto.setStackedPoints.call(this, axis, 'group');
155            // After updating, if we now have proper stacks, we must delete the
156            // group pseudo stacks (#14980)
157        }
158        else {
159            axis.stacking.resetStacks();
160        }
161    }
162}
163/**
164 * Adds series' points value to corresponding stack
165 *
166 * @private
167 * @function Highcharts.Series#setStackedPoints
168 */
169function seriesSetStackedPoints(axis, stackingParam) {
170    const type = stackingParam || this.options.stacking;
171    if (!type ||
172        !this.reserveSpace() ||
173        // Group stacks (centerInCategory) belong on the x-axis, other stacks on
174        // the y-axis.
175        ({ group: 'xAxis' }[type] || 'yAxis') !== axis.coll) {
176        return;
177    }
178    const series = this, xData = series.getColumn('x', true), yData = series.getColumn(series.pointValKey || 'y', true), stackedYData = [], yDataLength = yData.length, seriesOptions = series.options, threshold = seriesOptions.threshold || 0, stackThreshold = seriesOptions.startFromThreshold ? threshold : 0, stackOption = seriesOptions.stack, stackKey = stackingParam ?
179        `${series.type},${type}` : (series.stackKey || ''), negKey = '-' + stackKey, negStacks = series.negStacks, stacking = axis.stacking, stacks = stacking.stacks, oldStacks = stacking.oldStacks;
180    let stackIndicator, isNegative, stack, other, key, pointKey, i;
181    stacking.stacksTouched += 1;
182    // Loop over the non-null y values and read them into a local array
183    for (i = 0; i < yDataLength; i++) {
184        const x = xData[i] || 0, y = yData[i], yNumber = isNumber(y) && y || 0;
185        stackIndicator = series.getStackIndicator(stackIndicator, x, series.index);
186        pointKey = stackIndicator.key || '';
187        // Read stacked values into a stack based on the x value,
188        // the sign of y and the stack key. Stacking is also handled for null
189        // values (#739)
190        isNegative = negStacks && yNumber < (stackThreshold ? 0 : threshold);
191        key = isNegative ? negKey : stackKey;
192        // Create empty object for this stack if it doesn't exist yet
193        if (!stacks[key]) {
194            stacks[key] = {};
195        }
196        // Initialize StackItem for this x
197        if (!stacks[key][x]) {
198            if (oldStacks[key]?.[x]) {
199                stacks[key][x] = oldStacks[key][x];
200                stacks[key][x].total = null;
201            }
202            else {
203                stacks[key][x] = new StackItem(axis, axis.options.stackLabels, !!isNegative, x, stackOption);
204            }
205        }
206        // If the StackItem doesn't exist, create it first
207        stack = stacks[key][x];
208        if (y !== null) {
209            stack.points[pointKey] = stack.points[series.index] = [
210                pick(stack.cumulative, stackThreshold)
211            ];
212            // Record the base of the stack
213            if (!defined(stack.cumulative)) {
214                stack.base = pointKey;
215            }
216            stack.touched = stacking.stacksTouched;
217            // In area charts, if there are multiple points on the same X value,
218            // let the area fill the full span of those points
219            if (stackIndicator.index > 0 && series.singleStacks === false) {
220                stack.points[pointKey][0] = stack.points[series.index + ',' + x + ',0'][0];
221            }
222            // When updating to null, reset the point stack (#7493)
223        }
224        else {
225            delete stack.points[pointKey];
226            delete stack.points[series.index];
227        }
228        // Add value to the stack total
229        let total = stack.total || 0;
230        if (type === 'percent') {
231            // Percent stacked column, totals are the same for the positive and
232            // negative stacks
233            other = isNegative ? stackKey : negKey;
234            if (negStacks && stacks[other]?.[x]) {
235                other = stacks[other][x];
236                total = other.total = Math.max(other.total || 0, total) +
237                    Math.abs(yNumber);
238                // Percent stacked areas
239            }
240            else {
241                total = correctFloat(total + Math.abs(yNumber));
242            }
243        }
244        else if (type === 'group') {
245            // In this stack, the total is the number of valid points
246            if (isNumber(y)) {
247                total++;
248            }
249        }
250        else {
251            total = correctFloat(total + yNumber);
252        }
253        if (type === 'group') {
254            // This point's index within the stack, pushed to stack.points[1]
255            stack.cumulative = (total || 1) - 1;
256        }
257        else {
258            stack.cumulative = correctFloat(pick(stack.cumulative, stackThreshold) + yNumber);
259        }
260        stack.total = total;
261        if (y !== null) {
262            stack.points[pointKey].push(stack.cumulative);
263            stackedYData[i] = stack.cumulative;
264            stack.hasValidPoints = true;
265        }
266    }
267    if (type === 'percent') {
268        stacking.usePercentage = true;
269    }
270    if (type !== 'group') {
271        this.stackedYData = stackedYData; // To be used in getExtremes
272    }
273    // Reset old stacks
274    stacking.oldStacks = {};
275}
276/* *
277 *
278 *  Classes
279 *
280 * */
281/**
282 * Adds stacking support to axes.
283 * @private
284 * @class
285 */
286class AxisAdditions {
287    /* *
288     *
289     *  Constructors
290     *
291     * */
292    constructor(axis) {
293        this.oldStacks = {};
294        this.stacks = {};
295        this.stacksTouched = 0;
296        this.axis = axis;
297    }
298    /* *
299     *
300     *  Functions
301     *
302     * */
303    /**
304     * Build the stacks from top down
305     * @private
306     */
307    buildStacks() {
308        const stacking = this, axis = stacking.axis, axisSeries = axis.series, isXAxis = axis.coll === 'xAxis', reversedStacks = axis.options.reversedStacks, len = axisSeries.length;
309        let actualSeries, i;
310        this.resetStacks();
311        stacking.usePercentage = false;
312        i = len;
313        while (i--) {
314            actualSeries = axisSeries[reversedStacks ? i : len - i - 1];
315            if (isXAxis) {
316                actualSeries.setGroupedPoints(axis);
317            }
318            actualSeries.setStackedPoints(axis);
319        }
320        // Loop up again to compute percent and stream stack
321        if (!isXAxis) {
322            for (i = 0; i < len; i++) {
323                axisSeries[i].modifyStacks();
324            }
325        }
326        fireEvent(axis, 'afterBuildStacks');
327    }
328    /**
329     * @private
330     */
331    cleanStacks() {
332        if (this.oldStacks) {
333            this.stacks = this.oldStacks;
334            // Reset stacks
335            objectEach(this.stacks, (type) => {
336                objectEach(type, (stack) => {
337                    stack.cumulative = stack.total;
338                });
339            });
340        }
341    }
342    /**
343     * Set all the stacks to initial states and destroy unused ones.
344     * @private
345     */
346    resetStacks() {
347        objectEach(this.stacks, (type) => {
348            objectEach(type, (stack, x) => {
349                // Clean up memory after point deletion (#1044, #4320)
350                if (isNumber(stack.touched) &&
351                    stack.touched < this.stacksTouched) {
352                    stack.destroy();
353                    delete type[x];
354                    // Reset stacks
355                }
356                else {
357                    stack.total = null;
358                    stack.cumulative = null;
359                }
360            });
361        });
362    }
363    /**
364     * @private
365     */
366    renderStackTotals() {
367        const stacking = this, axis = stacking.axis, chart = axis.chart, renderer = chart.renderer, stacks = stacking.stacks, stackLabelsAnim = axis.options.stackLabels?.animation, animationConfig = getDeferredAnimation(chart, stackLabelsAnim || false), stackTotalGroup = stacking.stackTotalGroup = (stacking.stackTotalGroup ||
368            renderer
369                .g('stack-labels')
370                .attr({
371                zIndex: 6,
372                opacity: 0
373            })
374                .add());
375        // The plotLeft/Top will change when y axis gets wider so we need to
376        // translate the stackTotalGroup at every render call. See bug #506
377        // and #516
378        stackTotalGroup.translate(chart.plotLeft, chart.plotTop);
379        // Render each stack total
380        objectEach(stacks, (type) => {
381            objectEach(type, (stack) => {
382                stack.render(stackTotalGroup);
383            });
384        });
385        stackTotalGroup.animate({
386            opacity: 1
387        }, animationConfig);
388    }
389}
390/* *
391 *
392 *  Composition
393 *
394 * */
395var StackingAxis;
396(function (StackingAxis) {
397    /* *
398     *
399     *  Functions
400     *
401     * */
402    /**
403     * Extends axis with stacking support.
404     * @private
405     */
406    function compose(AxisClass, ChartClass, SeriesClass) {
407        const chartProto = ChartClass.prototype, seriesProto = SeriesClass.prototype;
408        if (!chartProto.getStacks) {
409            addEvent(AxisClass, 'init', onAxisInit);
410            addEvent(AxisClass, 'destroy', onAxisDestroy);
411            chartProto.getStacks = chartGetStacks;
412            seriesProto.getStackIndicator = seriesGetStackIndicator;
413            seriesProto.modifyStacks = seriesModifyStacks;
414            seriesProto.percentStacker = seriesPercentStacker;
415            seriesProto.setGroupedPoints = seriesSetGroupedPoints;
416            seriesProto.setStackedPoints = seriesSetStackedPoints;
417        }
418    }
419    StackingAxis.compose = compose;
420})(StackingAxis || (StackingAxis = {}));
421/* *
422 *
423 *  Default Export
424 *
425 * */
426export default StackingAxis;

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.