Skip to content

Commit

Permalink
v12.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
TorsteinHonsi committed Dec 17, 2024
1 parent 06333ab commit e9bb900
Show file tree
Hide file tree
Showing 331 changed files with 4,644 additions and 3,429 deletions.
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "highcharts",
"version": "12.0.2",
"version": "12.1.0",
"main": "highcharts.js",
"license": "https://www.highcharts.com/license",
"types": "highcharts.d.ts"
Expand Down
2 changes: 2 additions & 0 deletions es-modules/Accessibility/Options/A11yDefaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ const Options = {
/**
* When a series contains more points than this, we no longer expose
* information about individual points to screen readers.
* Note that the keyboard navigation remains functional, but points
* won't have accessible descriptions unless handled separately.
*
* Set to `false` to disable.
*
Expand Down
17 changes: 5 additions & 12 deletions es-modules/Core/Color/Color.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,18 +192,11 @@ class Color {
}
// Check for has alpha, because rgba colors perform worse due to
// lack of support in WebKit.
const hasAlpha = (toRgba[3] !== 1 || fromRgba[3] !== 1);
return (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))) :
'') +
')';
const hasAlpha = (toRgba[3] !== 1 || fromRgba[3] !== 1), channel = (to, i) => to + (fromRgba[i] - to) * (1 - pos), rgba = toRgba.slice(0, 3).map(channel).map(Math.round);
if (hasAlpha) {
rgba.push(channel(toRgba[3], 3));
}
return (hasAlpha ? 'rgba(' : 'rgb(') + rgba.join(',') + ')';
}
}
/* *
Expand Down
4 changes: 1 addition & 3 deletions es-modules/Core/Renderer/HTML/HTMLElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ class HTMLElement extends SVGElement {
textWidth,
this.textAlign
].join(','), parentPadding = (this.parentGroup?.padding * -1) || 0;
let baseline, hasBoxWidthChanged = false;
let baseline;
// 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
Expand All @@ -274,10 +274,8 @@ class HTMLElement extends SVGElement {
whiteSpace: whiteSpace || 'normal' // #3331
});
this.oldTextWidth = textWidth;
hasBoxWidthChanged = true; // #8159
}
}
this.hasBoxWidthChanged = hasBoxWidthChanged; // #8159
// Do the calculations and DOM access only if properties changed
if (currentTextTransform !== this.cTT) {
baseline = renderer.fontMetrics(element).b;
Expand Down
4 changes: 3 additions & 1 deletion es-modules/Core/Renderer/SVG/SVGElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,9 @@ class SVGElement {
* @return {Highcharts.SVGElement} Returns the SVGElement for chaining.
*/
align(alignOptions, alignByTranslate, alignTo, redraw = true) {
const attribs = {}, renderer = this.renderer, alignedObjects = renderer.alignedObjects, initialAlignment = Boolean(alignOptions);
const attribs = {
'text-align': alignOptions?.align
}, renderer = this.renderer, alignedObjects = renderer.alignedObjects, initialAlignment = Boolean(alignOptions);
// First call on instanciate
if (alignOptions) {
this.alignOptions = alignOptions;
Expand Down
19 changes: 8 additions & 11 deletions es-modules/Core/Renderer/SVG/SVGLabel.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class SVGLabel extends SVGElement {
* */
alignSetter(value) {
const alignFactor = getAlignFactor(value);
this.textAlign = value;
if (alignFactor !== this.alignFactor) {
this.alignFactor = alignFactor;
// Bounding box exists, means we're dynamically changing
Expand Down Expand Up @@ -246,6 +247,7 @@ class SVGLabel extends SVGElement {
}
'text-alignSetter'(value) {
this.textAlign = value;
this.updateTextPadding();
}
textSetter(text) {
if (typeof text !== 'undefined') {
Expand Down Expand Up @@ -315,24 +317,19 @@ class SVGLabel extends SVGElement {
* is changed.
*/
updateTextPadding() {
const text = this.text;
const text = this.text, textAlign = text.styles.textAlign || this.textAlign;
if (!text.textPath) {
this.updateBoxSize();
// Determine y based on the baseline
const textY = this.baseline ? 0 : this.baselineOffset, textX = (this.paddingLeft ?? this.padding) +
// Compensate for alignment
((defined(this.widthSetting) && this.bBox) ?
getAlignFactor(this.textAlign) *
(this.widthSetting - this.bBox.width) :
0);
getAlignFactor(textAlign) * (this.widthSetting ?? this.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) {
this.bBox = text.getBBox(true);
}
text.attr({
align: textAlign,
x: textX
});
if (typeof textY !== 'undefined') {
text.attr('y', textY);
}
Expand Down
4 changes: 3 additions & 1 deletion es-modules/Core/Series/DataLabel.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ var DataLabel;
(unrotatedbBox.width - bBox.width);
dataLabel.alignAttr.y += getAlignFactor(options.verticalAlign) *
(unrotatedbBox.height - bBox.height);
dataLabel[dataLabel.placed ? 'animate' : 'attr']({
dataLabel.attr({
'text-align': dataLabel.alignAttr['text-align'] || 'center'
})[dataLabel.placed ? 'animate' : 'attr']({
x: dataLabel.alignAttr.x +
(bBox.width - unrotatedbBox.width) / 2,
y: dataLabel.alignAttr.y +
Expand Down
28 changes: 13 additions & 15 deletions es-modules/Core/Series/Series.js
Original file line number Diff line number Diff line change
Expand Up @@ -2394,9 +2394,14 @@ class Series {
* @private
* @function Highcharts.Series#searchKDTree
*/
searchKDTree(point, compareX, e) {
searchKDTree(point, compareX, e, suppliedPointEvaluator, suppliedBSideCheckEvaluator) {
const series = this, [kdX, kdY] = this.kdAxisArray, kdComparer = compareX ? 'distX' : 'dist', kdDimensions = (series.options.findNearestPointBy || '')
.indexOf('y') > -1 ? 2 : 1, useRadius = !!series.isBubble;
.indexOf('y') > -1 ? 2 : 1, useRadius = !!series.isBubble, pointEvaluator = suppliedPointEvaluator || ((p1, p2, comparisonProp) => [
(p1[comparisonProp] || 0) < (p2[comparisonProp] || 0) ?
p1 :
p2,
false
]), bSideCheckEvaluator = suppliedBSideCheckEvaluator || ((a, b) => a < b);
/**
* Set the one and two dimensional distance on the point object.
* @private
Expand All @@ -2411,28 +2416,21 @@ class Series {
*/
function doSearch(search, tree, depth, dimensions) {
const point = tree.point, axis = series.kdAxisArray[depth % dimensions];
let nPoint1, nPoint2, ret = point;
let ret = point, flip = false;
setDistance(search, point);
// Pick side based on distance to splitting point
const tdist = (search[axis] || 0) - (point[axis] || 0) +
(useRadius ? (point.marker?.radius || 0) : 0), sideA = tdist < 0 ? 'left' : 'right', sideB = tdist < 0 ? 'right' : 'left';
// End of tree
if (tree[sideA]) {
nPoint1 = doSearch(search, tree[sideA], depth + 1, dimensions);
ret = (nPoint1[kdComparer] <
ret[kdComparer] ?
nPoint1 :
point);
[ret, flip] = pointEvaluator(point, doSearch(search, tree[sideA], depth + 1, dimensions), kdComparer);
}
if (tree[sideB]) {
const sqrtTDist = Math.sqrt(tdist * tdist), retDist = ret[kdComparer];
// Compare distance to current best to splitting point to decide
// whether to check side B or not
if (Math.sqrt(tdist * tdist) < ret[kdComparer]) {
nPoint2 = doSearch(search, tree[sideB], depth + 1, dimensions);
ret = (nPoint2[kdComparer] <
ret[kdComparer] ?
nPoint2 :
ret);
// whether to check side B or no
if (bSideCheckEvaluator(sqrtTDist, retDist, flip)) {
ret = pointEvaluator(ret, doSearch(search, tree[sideB], depth + 1, dimensions), kdComparer)[0];
}
}
return ret;
Expand Down
24 changes: 14 additions & 10 deletions es-modules/Core/Templating.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const { defaultOptions, defaultTime } = D;
import G from './Globals.js';
const { doc } = G;
import U from './Utilities.js';
const { extend, getNestedProperty, isArray, isNumber, isObject, pick, ucfirst } = U;
const { extend, getNestedProperty, isArray, isNumber, isObject, isString, pick, ucfirst } = U;
const helpers = {
// Built-in helpers
add: (a, b) => a + b,
Expand Down Expand Up @@ -48,6 +48,8 @@ const numberFormatCache = {};
* Functions
*
* */
// Internal convenience function
const isQuotedString = (str) => /^["'].+["']$/.test(str);
/**
* 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
Expand Down Expand Up @@ -125,11 +127,11 @@ function dateFormat(format, timestamp, upperCaseFirst) {
* The formatted string.
*/
function format(str = '', ctx, chart) {
const regex = /\{([\p{L}\d:\.,;\-\/<>\[\]%_@"'’= #\(\)]+)\}/gu,
const regex = /\{([\p{L}\d:\.,;\-\/<>\[\]%_@+"'’= #\(\)]+)\}/gu,
// The sub expression regex is the same as the top expression regex,
// but except parens and block helpers (#), and surrounded by parens
// instead of curly brackets.
subRegex = /\(([\p{L}\d:\.,;\-\/<>\[\]%_@"'= ]+)\)/gu, matches = [], floatRegex = /f$/, decRegex = /\.(\d)/, lang = chart?.options.lang || defaultOptions.lang, time = chart && chart.time || defaultTime, numberFormatter = chart && chart.numberFormatter || numberFormat;
subRegex = /\(([\p{L}\d:\.,;\-\/<>\[\]%_@+"'= ]+)\)/gu, matches = [], floatRegex = /f$/, decRegex = /\.(\d)/, lang = chart?.options.lang || defaultOptions.lang, time = chart && chart.time || defaultTime, numberFormatter = chart && chart.numberFormatter || numberFormat;
/*
* Get a literal or variable value inside a template expression. May be
* extended with other types like string or null if needed, but keep it
Expand All @@ -147,7 +149,7 @@ function format(str = '', ctx, chart) {
if ((n = Number(key)).toString() === key) {
return n;
}
if (/^["'].+["']$/.test(key)) {
if (isQuotedString(key)) {
return key.slice(1, -1);
}
// Variables and constants
Expand Down Expand Up @@ -260,7 +262,8 @@ function format(str = '', ctx, chart) {
// Simple variable replacement
}
else {
const valueAndFormat = expression.split(':');
const valueAndFormat = isQuotedString(expression) ?
[expression] : expression.split(':');
replacement = resolveProperty(valueAndFormat.shift() || '');
// Format the replacement
if (valueAndFormat.length && typeof replacement === 'number') {
Expand All @@ -273,13 +276,14 @@ function format(str = '', ctx, chart) {
}
else {
replacement = time.dateFormat(segment, replacement);
// Use string literal in order to be preserved in the outer
// expression
if (hasSub) {
replacement = `"${replacement}"`;
}
}
}
// Use string literal in order to be preserved in the outer
// expression
subRegex.lastIndex = 0;
if (subRegex.test(match.find) && isString(replacement)) {
replacement = `"${replacement}"`;
}
}
str = str.replace(match.find, pick(replacement, ''));
});
Expand Down
9 changes: 6 additions & 3 deletions es-modules/Core/Time.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ class Time {
* Properties
*
* */
this.options = {};
this.options = {
timezone: 'UTC'
};
this.variableTimezone = false;
this.Date = win.Date;
this.update(options);
Expand All @@ -113,12 +115,13 @@ class Time {
*
*/
update(options = {}) {
let timezone = options.timezone ?? 'UTC';
this.dTLCache = {};
this.options = options = merge(true, this.options, options);
const { timezoneOffset, useUTC } = options;
// Allow using a different Date class
this.Date = options.Date || win.Date || Date;
// Assign the time zone. Handle the legacy, deprecated `useUTC` option.
let timezone = options.timezone;
if (defined(useUTC)) {
timezone = useUTC ? 'UTC' : void 0;
}
Expand Down Expand Up @@ -561,7 +564,7 @@ class Time {
}
else if (isObject(format)) {
const tzHours = (this.getTimezoneOffset(timestamp) || 0) /
(60000 * 60), timeZone = this.options.timezone || ('Etc/GMT' + (tzHours >= 0 ? '+' : '') + tzHours), { prefix = '', suffix = '' } = format;
(60000 * 60), timeZone = this.timezone || ('Etc/GMT' + (tzHours >= 0 ? '+' : '') + tzHours), { prefix = '', suffix = '' } = format;
format = prefix + this.dateTimeFormat(extend({ timeZone }, format), timestamp) + suffix;
}
// Optionally sentence-case the string and return
Expand Down
2 changes: 1 addition & 1 deletion es-modules/Core/Utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,7 @@ function getNestedProperty(path, parent) {
}
return thisProp ?? parent;
}
const child = parent[pathElement];
const child = parent[pathElement.replace(/[\\'"]/g, '')];
// Filter on the child
if (!defined(child) ||
typeof child === 'function' ||
Expand Down
1 change: 1 addition & 0 deletions es-modules/Data/Converters/CSVConverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ CSVConverter.defaultOptions = {
...DataConverter.defaultOptions,
lineDelimiter: '\n'
};
DataConverter.registerType('CSV', CSVConverter);
/* *
*
* Default Export
Expand Down
31 changes: 31 additions & 0 deletions es-modules/Data/Converters/DataConverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* - Gøran Slettemark
* - Torstein Hønsi
* - Wojciech Chmiel
* - Jomar Hønsi
*
* */
'use strict';
Expand Down Expand Up @@ -560,11 +561,41 @@ DataConverter.defaultOptions = {
* Declarations
*
* */
/* *
*
* Constants
*
* */
/**
* Registry as a record object with connector names and their class.
*/
DataConverter.types = {};
/* *
*
* Functions
*
* */
/**
* Adds a converter class to the registry.
*
* @private
*
* @param {string} key
* Registry key of the converter class.
*
* @param {DataConverterTypes} DataConverterClass
* Connector class (aka class constructor) to register.
*
* @return {boolean}
* Returns true, if the registration was successful. False is returned, if
* their is already a converter registered with this key.
*/
function registerType(key, DataConverterClass) {
return (!!key &&
!DataConverter.types[key] &&
!!(DataConverter.types[key] = DataConverterClass));
}
DataConverter.registerType = registerType;
/**
* Converts an array of columns to a table instance. Second dimension of the
* array are the row cells.
Expand Down
1 change: 1 addition & 0 deletions es-modules/Data/Converters/GoogleSheetsConverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class GoogleSheetsConverter extends DataConverter {
GoogleSheetsConverter.defaultOptions = {
...DataConverter.defaultOptions
};
DataConverter.registerType('GoogleSheets', GoogleSheetsConverter);
/* *
*
* Default Export
Expand Down
1 change: 1 addition & 0 deletions es-modules/Data/Converters/HTMLTableConverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ HTMLTableConverter.defaultOptions = {
useRowspanHeaders: true,
useMultiLevelHeaders: true
};
DataConverter.registerType('HTMLTable', HTMLTableConverter);
/* *
*
* Default Export
Expand Down
1 change: 1 addition & 0 deletions es-modules/Data/Converters/JSONConverter.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ JSONConverter.defaultOptions = {
data: [],
orientation: 'rows'
};
DataConverter.registerType('JSON', JSONConverter);
/* *
*
* Default Export
Expand Down
Loading

0 comments on commit e9bb900

Please sign in to comment.