Carga
This commit is contained in:
2025-04-17 00:35:33 -06:00
parent 4977462629
commit 67fc72aed5
1333 changed files with 1077639 additions and 0 deletions

View File

@@ -0,0 +1,488 @@
/* *
*
* (c) 2012-2021 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
* - Gøran Slettemark
* - Torstein Hønsi
* - Wojciech Chmiel
*
* */
'use strict';
import U from './../Core/Utilities.js';
var merge = U.merge, isNumber = U.isNumber;
/* *
*
* Class
*
* */
/**
* Class to convert between common value types.
*/
var DataConverter = /** @class */ (function () {
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the Data Converter.
*
* @param {DataConverter.Options} [options]
* Options for the Data Converter.
*
* @param {DataConverter.ParseDateCallbackFunction} [parseDate]
* A function to parse string representations of dates
* into JavaScript timestamps.
*/
function DataConverter(options, parseDate) {
/**
* A collection of available date formats.
*
* @name Highcharts.Data#dateFormats
* @type {Highcharts.Dictionary<Highcharts.DataDateFormatObject>}
*/
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) {
var d = new Date();
if (!match) {
return NaN;
}
var year = +match[3];
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);
}
}
};
var decimalPoint;
this.options = merge(DataConverter.defaultOptions, options);
this.parseDateFn = parseDate;
decimalPoint = this.options.decimalPoint;
if (decimalPoint !== '.' && decimalPoint !== ',') {
decimalPoint = void 0;
}
this.decimalRegex = (decimalPoint &&
new RegExp('^(-?[0-9]+)' + decimalPoint + '([0-9]+)$'));
}
/* *
*
* Functions
*
* */
/**
* Getter for a date format.
*/
DataConverter.prototype.getDateFormat = function () {
return this.options.dateFormat;
};
/**
* Converts a value to a boolean.
*
* @param {DataConverter.Type} value
* Value to convert.
*
* @return {boolean}
* Converted value as a boolean.
*/
DataConverter.prototype.asBoolean = function (value) {
if (typeof value === 'boolean') {
return value;
}
if (typeof value === 'string') {
return value !== '' && value !== '0' && value !== 'false';
}
return !!this.asNumber(value);
};
/**
* Converts a value to a Date.
*
* @param {DataConverter.Type} value
* Value to convert.
*
* @return {globalThis.Date}
* Converted value as a Date.
*/
DataConverter.prototype.asDate = function (value) {
var timestamp;
if (typeof value === 'string') {
timestamp = this.parseDate(value);
}
else if (typeof value === 'number') {
timestamp = value;
}
else if (value instanceof Date) {
return value;
}
else {
timestamp = this.parseDate(this.asString(value));
}
return new Date(timestamp);
};
/**
* Converts a value to a number.
*
* @param {DataConverter.Type} value
* Value to convert.
*
* @return {number}
* Converted value as a number.
*/
DataConverter.prototype.asNumber = function (value) {
if (typeof value === 'number') {
return value;
}
if (typeof value === 'boolean') {
return value ? 1 : 0;
}
if (typeof value === 'string') {
if (value.indexOf(' ') > -1) {
value = value.replace(/\s+/g, '');
}
if (this.decimalRegex) {
value = value.replace(this.decimalRegex, '$1.$2');
}
return parseFloat(value);
}
if (value instanceof Date) {
return value.getDate();
}
if (value) {
return value.getRowCount();
}
return NaN;
};
/**
* Converts a value to a string.
*
* @param {DataConverter.Type} value
* Value to convert.
*
* @return {string}
* Converted value as a string.
*/
DataConverter.prototype.asString = function (value) {
return "".concat(value);
};
/**
* Trim a string from whitespaces.
*
* @param {string} str
* String to trim.
*
* @param {boolean} [inside=false]
* Remove all spaces between numbers.
*
* @return {string}
* Trimed string
*/
DataConverter.prototype.trim = function (str, inside) {
var converter = this;
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 (converter.decimalRegex) {
str = str.replace(converter.decimalRegex, '$1.$2');
}
}
return str;
};
/**
* Guesses the potential type of a string value
* (for parsing CSV etc)
*
* @param {string} value
* The string to examine
* @return {'number'|'string'|'Date'}
* `string`, `Date` or `number`
*/
DataConverter.prototype.guessType = function (value) {
var converter = this, trimVal = converter.trim(value), trimInsideVal = converter.trim(value, true), floatVal = parseFloat(trimInsideVal);
var result = 'string', dateVal;
// is numeric
if (+trimInsideVal === floatVal) {
// If the number is greater than milliseconds in a year, assume
// datetime.
if (floatVal > 365 * 24 * 3600 * 1000) {
result = 'Date';
}
else {
result = 'number';
}
// String, continue to determine if it is
// a date string or really a string.
}
else {
if (trimVal && trimVal.length) {
dateVal = converter.parseDate(value);
}
if (dateVal && isNumber(dateVal)) {
result = 'Date';
}
else {
result = 'string';
}
}
return result;
};
/**
* Casts a string value to it's guessed type
* @param {string} value
* The string to examine
*
* @return {number|string|Date}
* The converted value
*/
DataConverter.prototype.asGuessedType = function (value) {
var converter = this, typeMap = {
'number': converter.asNumber,
'Date': converter.asDate,
'string': converter.asString
};
return typeMap[converter.guessType(value)].call(converter, value);
};
/**
* Parse a date and return it as a number.
*
* @function Highcharts.Data#parseDate
*
* @param {string} value
* Value to parse.
*
* @param {string} dateFormatProp
* Which of the predefined date formats
* to use to parse date values.
*/
DataConverter.prototype.parseDate = function (value, dateFormatProp) {
var converter = this;
var dateFormat = dateFormatProp || converter.options.dateFormat, result = NaN, key, format, match;
if (converter.parseDateFn) {
result = converter.parseDateFn(value);
}
else {
// Auto-detect the date format the first time
if (!dateFormat) {
for (key in converter.dateFormats) { // eslint-disable-line guard-for-in
format = converter.dateFormats[key];
match = value.match(format.regex);
if (match) {
// converter.options.dateFormat = dateFormat = key;
dateFormat = key;
// converter.options.alternativeFormat =
// format.alternative || '';
result = format.parser(match);
break;
}
}
// Next time, use the one previously found
}
else {
format = converter.dateFormats[dateFormat];
if (!format) {
// The selected format is invalid
format = converter.dateFormats['YYYY/mm/dd'];
}
match = value.match(format.regex);
if (match) {
result = format.parser(match);
}
}
// Fall back to Date.parse
if (!match) {
match = Date.parse(value);
// External tools like Date.js and MooTools extend Date object
// and returns a date.
if (typeof match === 'object' &&
match !== null &&
match.getTime) {
result = (match.getTime() -
match.getTimezoneOffset() *
60000);
// Timestamp
}
else if (isNumber(match)) {
result = match - (new Date(match)).getTimezoneOffset() * 60000;
if ( // reset dates without year in Chrome
value.indexOf('2001') === -1 &&
(new Date(result)).getFullYear() === 2001) {
result = NaN;
}
}
}
}
return result;
};
/**
* 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
*
* @param {Array<string>} data
* Data to check the format.
*
* @param {number} limit
* Max data to check the format.
*
* @param {boolean} save
* Whether to save the date format in the converter options.
*/
DataConverter.prototype.deduceDateFormat = function (data, limit, save) {
var parser = this, stable = [], max = [];
var format = 'YYYY/mm/dd', thing, guessedFormat = [], i = 0, madeDeduction = false,
// candidates = {},
elem, 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) {
elem = parseInt(thing[j], 10);
if (elem) {
max[j] = (!max[j] || max[j] < elem) ? elem : max[j];
if (typeof stable[j] !== 'undefined') {
if (stable[j] !== elem) {
stable[j] = false;
}
}
else {
stable[j] = elem;
}
if (elem > 31) {
if (elem < 100) {
guessedFormat[j] = 'YY';
}
else {
guessedFormat[j] = 'YYYY';
}
// madeDeduction = true;
}
else if (elem > 12 &&
elem <= 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';
}
format = guessedFormat.join('/');
// If the caculated format is not valid, we need to present an
// error.
}
// Save the deduced format in the converter options.
if (save) {
parser.options.dateFormat = format;
}
return format;
};
/* *
*
* Static Properties
*
* */
/**
* Default options
*/
DataConverter.defaultOptions = {
dateFormat: '',
alternativeFormat: ''
};
return DataConverter;
}());
/* *
*
* Export
*
* */
export default DataConverter;

View File

@@ -0,0 +1,252 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
*
* */
'use strict';
/* *
*
* Imports
*
* */
import H from '../Core/Globals.js';
/* *
*
* Constants
*
* */
var win = H.win;
var delay = setTimeout;
/* *
*
* Class
*
* */
/**
* Simplified wrapper for Promise-support in outdated browsers.
*/
var DataPromise = /** @class */ (function () {
/* *
*
* Constructor
*
* */
function DataPromise(executor) {
/* *
*
* Properties
*
* */
this.jobs = [];
this.state = DataPromise.State.Pending;
this.value = void 0;
if (win.Promise && !DataPromise.onlyPolyfill) {
return new win.Promise(executor);
}
var promise = this;
delay(function () {
try {
executor(function (value) { return promise.resolved(value); }, function (reason) { return promise.rejected(reason); });
}
catch (e) {
promise.rejected(e);
}
}, 0);
}
/* *
*
* Static Functions
*
* */
DataPromise.isPromiseLike = function (promise) {
return (typeof promise === 'object' &&
promise !== null &&
typeof promise.then === 'function');
};
DataPromise.reject = function (reason) {
if (win.Promise && !DataPromise.onlyPolyfill) {
return win.Promise.reject(reason);
}
return new DataPromise(function (resolve, reject) { return reject(reason); });
};
DataPromise.resolve = function (value) {
if (win.Promise && !DataPromise.onlyPolyfill) {
return win.Promise.resolve(value);
}
if (DataPromise.isPromiseLike(value)) {
return new DataPromise(function (resolve, reject) {
value.then(resolve, reject);
});
}
return new DataPromise(function (resolve) { return resolve(value); });
};
/* *
*
* Functions
*
* */
DataPromise.prototype['catch'] = function (onrejected) {
return this.then(null, onrejected);
};
DataPromise.prototype.rejected = function (reason) {
var promise = this;
if (promise.state === DataPromise.State.Pending) {
promise.state = DataPromise.State.Rejected;
promise.reason = reason;
delay(function () { return promise.work(); }, 0);
}
};
DataPromise.prototype.resolved = function (value) {
var promise = this;
if (promise.state === DataPromise.State.Pending) {
if (DataPromise.isPromiseLike(value)) {
value.then(function (value) { return promise.resolved(value); }, function (reason) { return promise.rejected(reason); });
}
else {
promise.state = DataPromise.State.Fulfilled;
promise.value = value;
delay(function () { return promise.work(); }, 0);
}
}
};
DataPromise.prototype.then = function (onfulfilled, onrejected) {
var promise = this, newPromise = new DataPromise(function () { return void 0; }), rejecter = function (reason) {
if (onrejected) {
try {
var result = onrejected(reason);
if (result instanceof DataPromise) {
result.then(function (value) {
return newPromise.resolved(value);
}, function (reason) {
return newPromise.rejected(reason);
});
}
else {
newPromise.resolved(result);
}
return;
}
catch (e) {
reason = e;
}
}
if (newPromise.jobs.length) {
newPromise.rejected(reason);
}
else if (reason) {
throw reason;
}
else {
throw new Error('Unhandled exception');
}
}, resolver = function (value) {
if (onfulfilled) {
try {
var result = onfulfilled(value);
if (result instanceof DataPromise) {
result.then(function (value) {
return newPromise.resolved(value);
}, function (reason) {
return newPromise.rejected(reason);
});
}
else {
newPromise.resolved(result);
}
}
catch (e) {
rejecter(e);
}
}
else {
newPromise.resolved(value);
}
};
switch (promise.state) {
case DataPromise.State.Fulfilled:
resolver(promise.value);
break;
case DataPromise.State.Rejected:
rejecter(promise.reason);
break;
default:
promise.jobs.push({
resolve: resolver,
reject: rejecter
});
break;
}
return newPromise;
};
DataPromise.prototype.work = function () {
var promise = this, jobs = promise.jobs;
var job, rejectHandled;
while ((job = jobs.shift())) {
try {
if (promise.state === DataPromise.State.Fulfilled) {
job.resolve(promise.value);
}
else if (job.reject) {
rejectHandled = true;
job.reject(promise.reason);
}
}
catch (e) {
rejectHandled = false;
promise.reason = e;
promise.state = DataPromise.State.Rejected;
}
}
if (rejectHandled === false) {
if (promise.reason) {
throw promise.reason;
}
else {
throw new Error('Unhandled rejection');
}
}
};
/* *
*
* Static Properties
*
* */
DataPromise.onlyPolyfill = false;
return DataPromise;
}());
/* *
*
* Class Namespace
*
* */
(function (DataPromise) {
/* *
*
* Declarations
*
* */
/* *
*
* Enumerations
*
* */
var State;
(function (State) {
State[State["Fulfilled"] = 2] = "Fulfilled";
State[State["Pending"] = 0] = "Pending";
State[State["Rejected"] = 1] = "Rejected";
})(State = DataPromise.State || (DataPromise.State = {}));
})(DataPromise || (DataPromise = {}));
/* *
*
* Default Export
*
* */
export default DataPromise;

View File

@@ -0,0 +1,288 @@
/* *
*
* Imports
*
* */
import DataTable from './DataTable.js';
import U from '../Core/Utilities.js';
var addEvent = U.addEvent, fireEvent = U.fireEvent, isNumber = U.isNumber, merge = U.merge, wrap = U.wrap;
/* *
*
* Constants
*
* */
var composedClasses = [];
/* *
*
* Functions
*
* */
/**
* @private
*/
function wrapSeriesGeneratePoints(proceed) {
if (this.hasGroupedData) {
return proceed.call(this);
}
var PointClass = this.pointClass, cropStart = this.cropStart || 0, data = this.data || [], points = [], processedXData = this.processedXData, processedYData = this.processedYData;
var cursor, point;
for (var i = 0, iEnd = processedXData.length; i < iEnd; ++i) {
cursor = cropStart + i;
point = data[cursor];
if (!point) {
point = data[cursor] = (new PointClass()).init(this, processedYData[cursor], processedXData[i]);
}
point.index = cursor;
points[i] = point;
}
this.data = data;
this.points = points;
fireEvent(this, 'afterGeneratePoints');
}
/**
* @private
*/
function wrapSeriesSetData(proceed, data, redraw, animation) {
if (data === void 0) { data = []; }
if (redraw === void 0) { redraw = true; }
var datas = this.datas;
if (this.hasGroupedData || !this.options.dataAsColumns) {
return proceed.call(this, data, redraw, animation);
}
data = this.options.data = this.userOptions.data = (this.chart.options.chart.allowMutatingData ?
(data || []) :
merge(true, data));
var columns = {}, keys = (this.options.keys || this.parallelArrays).slice();
if (isNumber(data[0]) || keys.length === 1) {
// first column is implicit index
var xData = columns.x = [];
for (var i = 0, iEnd = data.length; i < iEnd; ++i) {
xData.push(this.autoIncrement());
}
columns[keys[1] || 'y'] = data;
}
else {
if (keys.indexOf('x') === -1 && keys.length > data.length) {
// first column is implicit index
var xData = columns.x = [];
for (var i = 0, iEnd = data.length; i < iEnd; ++i) {
xData.push(this.autoIncrement());
}
}
for (var i = 0, iEnd = Math.min(data.length, keys.length); i < iEnd; ++i) {
if (data[i] instanceof Array) {
columns[keys[i]] = data[i];
}
}
}
datas.setTable(new DataTable(columns, this.name));
}
/* *
*
* Class
*
* */
var DataSeriesAdditions = /** @class */ (function () {
/* *
*
* Constructor
*
* */
function DataSeriesAdditions(series) {
this.unlisteners = [];
var columns = {}, keys = series.parallelArrays;
for (var i = 0, iEnd = keys.length; i < iEnd; ++i) {
columns[keys[i]] = [];
}
this.series = series;
this.table = new DataTable();
}
/* *
*
* Static Functions
*
* */
/**
* @private
*/
DataSeriesAdditions.compose = function (SeriesClass) {
if (composedClasses.indexOf(SeriesClass) === -1) {
composedClasses.push(SeriesClass);
addEvent(SeriesClass, 'init', function () {
this.datas = new DataSeriesAdditions(this);
});
var seriesProto = SeriesClass.prototype;
wrap(seriesProto, 'generatePoints', wrapSeriesGeneratePoints);
wrap(seriesProto, 'setData', wrapSeriesSetData);
}
};
/* *
*
* Functions
*
* */
/**
* Triggers processing and redrawing
* @private
*/
DataSeriesAdditions.prototype.processTable = function (redraw, animation) {
var series = this.series;
if (series.options.legendType === 'point') {
series.processData();
series.generatePoints();
}
if (redraw) {
var chart = series.chart;
series.isDirty = chart.isDirtyBox = true;
series.isDirtyData = true;
chart.redraw(animation);
}
};
/**
* Experimental integration of the data layer
* @private
*/
DataSeriesAdditions.prototype.setTable = function (table, redraw, animation) {
if (redraw === void 0) { redraw = true; }
var series = this.series, anySeries = series, oldData = series.points, keys = series.parallelArrays, rowCount = table.getRowCount();
var key;
if (oldData) {
var xAxis = series.xAxis;
series.colorCounter = 0;
series.data = [];
delete anySeries.points;
delete anySeries.processedXData;
delete anySeries.processedYData;
delete anySeries.xIncrement;
for (var i = 0, iEnd = keys.length; i < iEnd; ++i) {
key = keys[i];
anySeries["".concat(key, "Data")] = [];
}
for (var i = 0, iEnd = oldData.length; i < iEnd; ++i) {
if (oldData[i] && (oldData[i].destroy)) {
oldData[i].destroy();
}
}
if (xAxis) {
xAxis.minRange = xAxis.userMinRange;
}
}
var column, failure = false, indexAsX = false;
for (var i = 0, iEnd = keys.length; i < iEnd; ++i) {
key = keys[i];
column = table.getColumn(key, true);
if (!column) {
if (key === 'x') {
indexAsX = true;
continue;
}
else {
failure = true;
break;
}
}
anySeries["".concat(key, "Data")] = column;
}
if (failure) {
// fallback to index
var columnNames = table.getColumnNames(), emptyColumn = [];
emptyColumn.length = rowCount;
var columnOffset = 0;
if (columnNames.length === keys.length - 1) {
// table index becomes x
columnOffset = 1;
indexAsX = true;
}
for (var i = columnOffset, iEnd = keys.length; i < iEnd; ++i) {
column = table.getColumn(columnNames[i], true);
key = keys[i];
anySeries["".concat(key, "Data")] = column || emptyColumn.slice();
}
}
this.indexAsX = indexAsX;
if (indexAsX && keys.indexOf('x') !== -1) {
column = [];
for (var x = 0; x < rowCount; ++x) {
column.push(series.autoIncrement());
}
anySeries.xData = column;
}
this.syncOff();
this.table = table;
if (redraw) {
this.syncOn();
}
this.processTable(redraw, oldData && animation);
};
/**
* Stops synchronisation of table changes with series.
* @private
*/
DataSeriesAdditions.prototype.syncOff = function () {
var unlisteners = this.unlisteners;
for (var i = 0, iEnd = unlisteners.length; i < iEnd; ++i) {
unlisteners[i]();
}
unlisteners.length = 0;
};
/**
* Activates synchronization of table changes with series.
* @private
*/
DataSeriesAdditions.prototype.syncOn = function () {
var _this = this;
if (this.unlisteners.length) {
return;
}
var series = this.series, table = this.table, anySeries = series, onChange = function (e) {
if (e.type === 'afterDeleteColumns') {
// deletion affects all points
_this.setTable(table, true);
return;
}
if (e.type === 'afterDeleteRows') {
if (e.rowIndex > 0 &&
e.rowIndex + e.rowCount < series.points.length) {
// deletion affects trailing points
_this.setTable(table, true);
return;
}
for (var i = e.rowIndex, iEnd = i + e.rowCount; i < iEnd; ++i) {
series.removePoint(i, false);
}
}
if (_this.indexAsX) {
if (e.type === 'afterSetCell') {
anySeries.xData[e.rowIndex] = e.rowIndex;
}
else if (e.type === 'afterSetRows') {
for (var i = e.rowIndex, iEnd = i + e.rowCount; i < iEnd; ++i) {
anySeries.xData[i] = series.autoIncrement();
}
}
}
_this.processTable(true);
};
this.unlisteners.push(table.on('afterDeleteColumns', onChange), table.on('afterDeleteRows', onChange), table.on('afterSetCell', onChange), table.on('afterSetRows', onChange));
};
return DataSeriesAdditions;
}());
/* *
*
* Default Export
*
* */
export default DataSeriesAdditions;
/* *
*
* API Options
*
* */
/**
* Indicates data is structured as columns instead of rows.
*
* @type {boolean}
* @requires es-modules/Data/DataSeriesComposition.js
* @apioption plotOptions.series.dataAsColumns
*/
(''); // keeps doclets above in JS file

View File

@@ -0,0 +1,207 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sebastian Bochan
* - Wojciech Chmiel
* - Sophie Bremer
*
* */
'use strict';
import DataTable from './DataTable.js';
import U from '../Core/Utilities.js';
var defined = U.defined, uniqueKey = U.uniqueKey;
/* *
*
* Class
*
* */
/**
* Class to convert Highcharts series data to table and get series data from the
* table.
*
* @private
*/
var DataSeriesConverter = /** @class */ (function () {
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the DataSeriesConverter class.
*
* @param {DataTable} [table]
* DataSeriesConverter table to store series data.
*
* @param {DataSeriesConverter.Options} [options]
* DataSeriesConverter options.
*/
function DataSeriesConverter(table, options) {
if (table === void 0) { table = new DataTable(); }
if (options === void 0) { options = {}; }
this.table = table;
this.options = options;
this.seriesIdMap = {};
this.seriesMeta = [];
}
/* *
*
* Functions
*
* */
/**
* Get the specific series data stored in the converter.
*
* @param {string} seriesId
* The id of the series.
*
* @return {Array<PointOptions>}
* Returns an array of series points opitons.
*/
DataSeriesConverter.prototype.getSeriesData = function (seriesId) {
var converter = this, table = converter.table, seriesData = [];
var pointOptions, cellName, cell, isCellFound, pointArrayMap;
if (seriesId) {
pointArrayMap = converter.seriesIdMap[seriesId].pointArrayMap || ['y'];
for (var i = 0, iEnd = table.getRowCount(); i < iEnd; i++) {
isCellFound = false;
pointOptions = {
x: table.getCellAsNumber('x', i, true)
};
for (var j = 0, jEnd = pointArrayMap.length; j < jEnd; j++) {
cellName = pointArrayMap[j] + '_' + seriesId;
cell = table.getCell(cellName, i);
if (typeof cell !== 'undefined') {
isCellFound = true;
pointOptions[pointArrayMap[j]] = table.getCellAsNumber(cellName, i);
}
}
if (isCellFound) {
seriesData.push(pointOptions);
}
}
}
return seriesData;
};
/**
* Get all series data stored in the converter.
*
* @return {Array<SeriesOptions>}
* Returns an array of series opitons.
*/
DataSeriesConverter.prototype.getAllSeriesData = function () {
var converter = this, seriesOptions = [];
var id;
for (var i = 0, iEnd = converter.seriesMeta.length; i < iEnd; i++) {
id = converter.seriesMeta[i].id;
seriesOptions.push({
id: id,
data: converter.getSeriesData(id)
});
}
return seriesOptions;
};
/**
* Update the converter with passed series options.
*
* @param {Array<LineSeries>} allSeries
* Array of series options to store in the converter.
*
* @param {DataEventEmitter.EventDetail} eventDetail
* Custom information for pending events.
*/
DataSeriesConverter.prototype.updateTable = function (allSeries, eventDetail) {
var table = this.table;
var columns, series, seriesMeta, pointArrayMap, pointArrayMapLength, options, keys, data, elem, rowIndex, y, needsArrayMap, xIndex, yIndex, yValueName, yValueIndex, yValueId, id;
if (allSeries && allSeries.length) {
this.options.seriesOptions = [];
this.seriesMeta = [];
this.seriesIdMap = {};
for (var i = 0, iEnd = allSeries.length; i < iEnd; i++) {
series = allSeries[i];
// Add a unique ID to the series if none is assigned.
series.id = defined(series.id) ? series.id : uniqueKey();
yValueId = '_' + series.id;
pointArrayMap = series.pointArrayMap || ['y'];
pointArrayMapLength = pointArrayMap.length;
options = series.options;
keys = options.keys;
data = series.options.data || [];
seriesMeta = {
id: series.id,
pointArrayMap: pointArrayMap,
options: series.options
};
this.options.seriesOptions.push(series.options);
this.seriesMeta.push(seriesMeta);
this.seriesIdMap[series.id] = seriesMeta;
for (var j = 0, jEnd = data.length; j < jEnd; j++) {
elem = data[j];
y = 'y' + yValueId;
columns = {};
needsArrayMap = pointArrayMapLength > 1;
if (typeof elem === 'number') {
columns[y] = elem;
columns.x = j;
}
else if (elem instanceof Array) {
xIndex = keys && keys.indexOf('x') > -1 ?
keys.indexOf('x') : 0;
yIndex = keys && keys.indexOf('y') > -1 ?
keys.indexOf('y') : 1;
if (needsArrayMap) {
for (var k = 0; k < pointArrayMapLength; k++) {
yValueIndex = keys && keys.indexOf(pointArrayMap[k]) > -1 ?
keys.indexOf(pointArrayMap[k]) :
k + elem.length - pointArrayMapLength;
yValueName = pointArrayMap[k];
columns[yValueName + yValueId] = elem[yValueIndex];
}
}
else {
columns[y] = elem[yIndex];
}
columns.x = elem.length - pointArrayMapLength > 0 ?
elem[xIndex] :
j;
}
else if (elem instanceof Object) {
if (needsArrayMap) {
var elemSet = elem;
for (var k = 0; k < pointArrayMapLength; k++) {
yValueName = pointArrayMap[k];
columns[yValueName + yValueId] = elemSet[yValueName];
}
}
else {
columns[y] = elem.y;
}
columns.x = elem.x || j;
}
id = '' + columns.x;
rowIndex = table.getRowIndexBy('id', id);
if (!rowIndex) {
columns.id = id;
table.setRows([columns], void 0, eventDetail);
}
else if (columns[y]) {
table.setCell(y, rowIndex, columns[y], eventDetail);
}
}
}
}
};
return DataSeriesConverter;
}());
/* *
*
* Export
*
* */
export default DataSeriesConverter;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,301 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import DataModifier from './DataModifier.js';
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* *
*
* Class
*
* */
/**
* Modifies a table with the help of modifiers in an ordered chain.
*
* @private
*/
var ChainModifier = /** @class */ (function (_super) {
__extends(ChainModifier, _super);
/* *
*
* Constructors
*
* */
/**
* Constructs an instance of the modifier chain.
*
* @param {DeepPartial<ChainModifier.Options>} [options]
* Options to configure the modifier chain.
*
* @param {...DataModifier} [modifiers]
* Modifiers in order for the modifier chain.
*/
function ChainModifier(options) {
var modifiers = [];
for (var _i = 1; _i < arguments.length; _i++) {
modifiers[_i - 1] = arguments[_i];
}
var _this = _super.call(this) || this;
_this.modifiers = modifiers;
_this.options = merge(ChainModifier.defaultOptions, options);
return _this;
}
/* *
*
* Functions
*
* */
/**
* Adds a configured modifier to the end of the modifier chain. Please note,
* that the modifier can be added multiple times.
*
* @param {DataModifier} modifier
* Configured modifier to add.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*/
ChainModifier.prototype.add = function (modifier, eventDetail) {
this.emit({
type: 'addModifier',
detail: eventDetail,
modifier: modifier
});
this.modifiers.push(modifier);
this.emit({
type: 'addModifier',
detail: eventDetail,
modifier: modifier
});
};
/**
* Clears all modifiers from the chain.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*/
ChainModifier.prototype.clear = function (eventDetail) {
this.emit({
type: 'clearChain',
detail: eventDetail
});
this.modifiers.length = 0;
this.emit({
type: 'afterClearChain',
detail: eventDetail
});
};
/**
* Applies partial modifications of a cell change to the property `modified`
* of the given modified table.
*
* *Note:* The `modified` property of the table gets replaced.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {string} columnName
* Column name of changed cell.
*
* @param {number|undefined} rowIndex
* Row index of changed cell.
*
* @param {Highcharts.DataTableCellType} cellValue
* Changed cell value.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
ChainModifier.prototype.modifyCell = function (table, columnName, rowIndex, cellValue, eventDetail) {
var modifiers = (this.options.reverse ?
this.modifiers.reverse() :
this.modifiers);
if (modifiers.length) {
var clone = table.clone();
for (var i = 0, iEnd = modifiers.length; i < iEnd; ++i) {
modifiers[i].modifyCell(clone, columnName, rowIndex, cellValue, eventDetail);
clone = clone.modified;
}
table.modified = clone;
}
return table;
};
/**
* Applies partial modifications of column changes to the property
* `modified` of the given table.
*
* *Note:* The `modified` property of the table gets replaced.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {Highcharts.DataTableColumnCollection} columns
* Changed columns as a collection, where the keys are the column names.
*
* @param {number} [rowIndex=0]
* Index of the first changed row.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
ChainModifier.prototype.modifyColumns = function (table, columns, rowIndex, eventDetail) {
var modifiers = (this.options.reverse ?
this.modifiers.reverse() :
this.modifiers.slice());
if (modifiers.length) {
var clone = table.clone();
for (var i = 0, iEnd = modifiers.length; i < iEnd; ++i) {
modifiers[i].modifyColumns(clone, columns, rowIndex, eventDetail);
clone = clone.modified;
}
table.modified = clone;
}
return table;
};
/**
* Applies partial modifications of row changes to the property `modified`
* of the given table.
*
* *Note:* The `modified` property of the table gets replaced.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
* Changed rows.
*
* @param {number} [rowIndex]
* Index of the first changed row.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
ChainModifier.prototype.modifyRows = function (table, rows, rowIndex, eventDetail) {
var modifiers = (this.options.reverse ?
this.modifiers.reverse() :
this.modifiers.slice());
if (modifiers.length) {
var clone = table.clone();
for (var i = 0, iEnd = modifiers.length; i < iEnd; ++i) {
modifiers[i].modifyRows(clone, rows, rowIndex, eventDetail);
clone = clone.modified;
}
table.modified = clone;
}
return table;
};
/**
* Applies several modifications to the table.
*
* *Note:* The `modified` property of the table gets replaced.
*
* @param {DataTable} table
* Table to modify.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {DataTable}
* Table as a reference.
*
* @emits ChainDataModifier#execute
* @emits ChainDataModifier#afterExecute
*/
ChainModifier.prototype.modifyTable = function (table, eventDetail) {
var chain = this;
chain.emit({ type: 'modify', detail: eventDetail, table: table });
var modifiers = (chain.options.reverse ?
chain.modifiers.reverse() :
chain.modifiers.slice());
var modified = table.modified;
for (var i = 0, iEnd = modifiers.length, modifier = void 0; i < iEnd; ++i) {
modifier = modifiers[i];
modified = modifier.modifyTable(modified).modified;
}
table.modified = modified;
chain.emit({ type: 'afterModify', detail: eventDetail, table: table });
return table;
};
/**
* Removes a configured modifier from all positions of the modifier chain.
*
* @param {DataModifier} modifier
* Configured modifier to remove.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*/
ChainModifier.prototype.remove = function (modifier, eventDetail) {
var modifiers = this.modifiers;
this.emit({
type: 'removeModifier',
detail: eventDetail,
modifier: modifier
});
modifiers.splice(modifiers.indexOf(modifier), 1);
this.emit({
type: 'afterRemoveModifier',
detail: eventDetail,
modifier: modifier
});
};
/* *
*
* Static Properties
*
* */
/**
* Default option for the ordered modifier chain.
*/
ChainModifier.defaultOptions = {
modifier: 'Chain',
reverse: false
};
return ChainModifier;
}(DataModifier));
/* *
*
* Register
*
* */
DataModifier.addModifier(ChainModifier);
/* *
*
* Export
*
* */
export default ChainModifier;

View File

@@ -0,0 +1,303 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
* - Gøran Slettemark
*
* */
'use strict';
import DataPromise from '../DataPromise.js';
import U from '../../Core/Utilities.js';
var addEvent = U.addEvent, fireEvent = U.fireEvent, merge = U.merge;
/** eslint-disable valid-jsdoc */
/* *
*
* Class
*
* */
/**
* Abstract class to provide an interface for modifying a table.
*
* @private
*/
var DataModifier = /** @class */ (function () {
function DataModifier() {
}
/* *
*
* Static Functions
*
* */
/**
* Adds a modifier class to the registry. The modifier has to provide the
* `DataModifier.options` property and the `DataModifier.execute` method to
* modify the table.
*
* @param {DataModifier} modifier
* Modifier class (aka class constructor) to register.
*
* @return {boolean}
* Returns true, if the registration was successful. False is returned, if
* their is already a modifier registered with this name.
*/
DataModifier.addModifier = function (modifier) {
var name = DataModifier.getName(modifier), registry = DataModifier.registry;
if (typeof name === 'undefined' ||
registry[name]) {
return false;
}
registry[name] = modifier;
return true;
};
/**
* Returns all registered modifier names.
*
* @return {Array<string>}
* All registered modifier names.
*/
DataModifier.getAllModifierNames = function () {
return Object.keys(DataModifier.registry);
};
/**
* Returns a copy of the modifier registry as record object with
* modifier names and their modifier class.
*
* @return {Record<string,DataModifierRegistryType>}
* Copy of the modifier registry.
*/
DataModifier.getAllModifiers = function () {
return merge(DataModifier.registry);
};
/**
* Returns a modifier class (aka class constructor) of the given modifier
* name.
*
* @param {string} name
* Registered class name of the class type.
*
* @return {DataModifier|undefined}
* Class type, if the class name was found, otherwise `undefined`.
*/
DataModifier.getModifier = function (name) {
return DataModifier.registry[name];
};
/**
* Extracts the name from a given modifier class.
*
* @param {DataModifier} modifier
* Modifier class to extract the name from.
*
* @return {string}
* Modifier name, if the extraction was successful, otherwise an empty
* string.
*/
DataModifier.getName = function (modifier) {
return (modifier.toString().match(DataModifier.nameRegExp) ||
['', ''])[1];
};
/* *
*
* Functions
*
* */
/**
* Runs a timed execution of the modifier on the given datatable.
* Can be configured to run multiple times.
*
* @param {DataTable} dataTable
* The datatable to execute
*
* @param {DataModifier.BenchmarkOptions} options
* Options. Currently supports `iterations` for number of iterations.
*
* @return {Array<number>}
* An array of times in milliseconds
*
*/
DataModifier.prototype.benchmark = function (dataTable, options) {
var results = [];
var modifier = this;
var execute = function () {
modifier.modifyTable(dataTable);
modifier.emit({ type: 'afterBenchmarkIteration' });
};
var defaultOptions = {
iterations: 1
};
var iterations = merge(defaultOptions, options).iterations;
modifier.on('afterBenchmarkIteration', function () {
if (results.length === iterations) {
modifier.emit({ type: 'afterBenchmark', results: results });
return;
}
// Run again
execute();
});
var times = {
startTime: 0,
endTime: 0
};
// Add timers
modifier.on('modify', function () {
times.startTime = window.performance.now();
});
modifier.on('afterModify', function () {
times.endTime = window.performance.now();
results.push(times.endTime - times.startTime);
});
// Initial run
execute();
return results;
};
/**
* Emits an event on the modifier to all registered callbacks of this event.
*
* @param {DataEventEmitter.Event} [e]
* Event object containing additonal event information.
*/
DataModifier.prototype.emit = function (e) {
fireEvent(this, e.type, e);
};
/**
* Returns a modified copy of the given table.
*
* @param {Highcharts.DataTable} table
* Table to modify.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Promise<Highcharts.DataTable>}
* Table with `modified` property as a reference.
*/
DataModifier.prototype.modify = function (table, eventDetail) {
var modifier = this;
return new DataPromise(function (resolve, reject) {
if (table.modified === table) {
table.modified = table.clone(false, eventDetail);
}
try {
resolve(modifier.modifyTable(table, eventDetail));
}
catch (e) {
modifier.emit({
type: 'error',
detail: eventDetail,
table: table
});
reject(e);
}
});
};
/**
* Applies partial modifications of a cell change to the property `modified`
* of the given modified table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {string} columnName
* Column name of changed cell.
*
* @param {number|undefined} rowIndex
* Row index of changed cell.
*
* @param {Highcharts.DataTableCellType} cellValue
* Changed cell value.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
DataModifier.prototype.modifyCell = function (table, columnName, rowIndex, cellValue, eventDetail) {
return this.modifyTable(table);
};
/**
* Applies partial modifications of column changes to the property
* `modified` of the given table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {Highcharts.DataTableColumnCollection} columns
* Changed columns as a collection, where the keys are the column names.
*
* @param {number} [rowIndex=0]
* Index of the first changed row.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
DataModifier.prototype.modifyColumns = function (table, columns, rowIndex, eventDetail) {
return this.modifyTable(table);
};
/**
* Applies partial modifications of row changes to the property `modified`
* of the given table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
* Changed rows.
*
* @param {number} [rowIndex]
* Index of the first changed row.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
DataModifier.prototype.modifyRows = function (table, rows, rowIndex, eventDetail) {
return this.modifyTable(table);
};
/**
* Registers a callback for a specific modifier event.
*
* @param {string} type
* Event type as a string.
*
* @param {DataEventEmitter.EventCallback} callback
* Function to register for an modifier callback.
*
* @return {Function}
* Function to unregister callback from the modifier event.
*/
DataModifier.prototype.on = function (type, callback) {
return addEvent(this, type, callback);
};
/* *
*
* Static Properties
*
* */
/**
* Regular expression to extract the modifier name (group 1) from the
* stringified class type.
*/
DataModifier.nameRegExp = (/^function\s+(\w*?)(?:Data)?(?:Modifier)?\s*\(/);
/**
* Registry as a record object with modifier names and their class.
*/
DataModifier.registry = {};
return DataModifier;
}());
/* *
*
* Export
*
* */
export default DataModifier;

View File

@@ -0,0 +1,146 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import DataModifier from './DataModifier.js';
import DataTable from '../DataTable.js';
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* *
*
* Class
*
* */
/**
* Groups table rows into subtables depending on column values.
*
* @private
*/
var GroupModifier = /** @class */ (function (_super) {
__extends(GroupModifier, _super);
/* *
*
* Constructors
*
* */
/**
* Constructs an instance of the group modifier.
*
* @param {GroupModifier.Options} [options]
* Options to configure the group modifier.
*/
function GroupModifier(options) {
var _this = _super.call(this) || this;
_this.options = merge(GroupModifier.defaultOptions, options);
return _this;
}
/* *
*
* Functions
*
* */
/**
* Applies modifications to the table rows and returns a new table with
* subtable, containing the grouped rows. The rows of the new table contain
* three columns:
* - `groupBy`: Column name used to group rows by.
* - `table`: Subtable containing the grouped rows.
* - `value`: containing the common value of the group
*
* @param {DataTable} table
* Table to modify.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {DataTable}
* Table with `modified` property as a reference.
*/
GroupModifier.prototype.modifyTable = function (table, eventDetail) {
var modifier = this;
modifier.emit({ type: 'modify', detail: eventDetail, table: table });
var byGroups = [], tableGroups = [], valueGroups = [], groupColumn = (modifier.options.groupColumn ||
table.getColumnNames()[0]), valueColumn = (table.getColumn(groupColumn) ||
[]), _a = modifier.options, invalidValues = _a.invalidValues, validValues = _a.validValues, modified = table.modified = table.clone(true, eventDetail);
var value, valueIndex;
for (var i = 0, iEnd = valueColumn.length; i < iEnd; ++i) {
value = valueColumn[i];
if (typeof value !== 'undefined') {
if (value instanceof DataTable ||
(invalidValues &&
invalidValues.indexOf(value) >= 0) || (validValues &&
validValues.indexOf(value) === -1)) {
continue;
}
valueIndex = valueGroups.indexOf(value);
if (valueIndex === -1) {
var newTable = new DataTable();
newTable.setRows([table.getRowObject(i) || {}]);
byGroups.push(groupColumn);
tableGroups.push(newTable);
valueGroups.push(value);
}
else {
tableGroups[valueIndex].setRows([table.getRow(i) || []]);
}
}
}
modified.deleteColumns();
modified.setColumns({
groupBy: byGroups,
table: tableGroups,
value: valueGroups
});
modifier.emit({ type: 'afterModify', detail: eventDetail, table: table });
return table;
};
/* *
*
* Static Properties
*
* */
/**
* Default options to group table rows.
*/
GroupModifier.defaultOptions = {
modifier: 'Group',
groupColumn: ''
};
return GroupModifier;
}(DataModifier));
/* *
*
* Register
*
* */
DataModifier.addModifier(GroupModifier);
/* *
*
* Export
*
* */
export default GroupModifier;

View File

@@ -0,0 +1,256 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Wojciech Chmiel
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import DataModifier from './DataModifier.js';
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* *
*
* Class
*
* */
/**
* Inverts columns and rows in a table.
*
* @private
*/
var InvertModifier = /** @class */ (function (_super) {
__extends(InvertModifier, _super);
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the invert modifier.
*
* @param {InvertModifier.Options} [options]
* Options to configure the invert modifier.
*/
function InvertModifier(options) {
var _this = _super.call(this) || this;
_this.options = merge(InvertModifier.defaultOptions, options);
return _this;
}
/* *
*
* Functions
*
* */
/**
* Applies partial modifications of a cell change to the property `modified`
* of the given modified table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {string} columnName
* Column name of changed cell.
*
* @param {number|undefined} rowIndex
* Row index of changed cell.
*
* @param {Highcharts.DataTableCellType} cellValue
* Changed cell value.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
InvertModifier.prototype.modifyCell = function (table, columnName, rowIndex, cellValue, eventDetail) {
var modified = table.modified, modifiedRowIndex = modified.getRowIndexBy('columnNames', columnName);
if (typeof modifiedRowIndex === 'undefined') {
modified.setColumns(this.modifyTable(table.clone()).getColumns(), void 0, eventDetail);
}
else {
modified.setCell("".concat(rowIndex), modifiedRowIndex, cellValue, eventDetail);
}
return table;
};
/**
* Applies partial modifications of column changes to the property
* `modified` of the given table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {Highcharts.DataTableColumnCollection} columns
* Changed columns as a collection, where the keys are the column names.
*
* @param {number} [rowIndex=0]
* Index of the first changed row.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
InvertModifier.prototype.modifyColumns = function (table, columns, rowIndex, eventDetail) {
var modified = table.modified, modifiedColumnNames = (modified.getColumn('columnNames') || []);
var columnNames = table.getColumnNames(), reset = (table.getRowCount() !== modifiedColumnNames.length);
if (!reset) {
for (var i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
if (columnNames[i] !== modifiedColumnNames[i]) {
reset = true;
break;
}
}
}
if (reset) {
return this.modifyTable(table, eventDetail);
}
columnNames = Object.keys(columns);
for (var i = 0, iEnd = columnNames.length, column = void 0, columnName = void 0, modifiedRowIndex = void 0; i < iEnd; ++i) {
columnName = columnNames[i];
column = columns[columnName];
modifiedRowIndex = (modified.getRowIndexBy('columnNames', columnName) ||
modified.getRowCount());
for (var j = 0, j2 = rowIndex, jEnd = column.length; j < jEnd; ++j, ++j2) {
modified.setCell("".concat(j2), modifiedRowIndex, column[j], eventDetail);
}
}
return table;
};
/**
* Applies partial modifications of row changes to the property `modified`
* of the given table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
* Changed rows.
*
* @param {number} [rowIndex]
* Index of the first changed row.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
InvertModifier.prototype.modifyRows = function (table, rows, rowIndex, eventDetail) {
var columnNames = table.getColumnNames(), modified = table.modified, modifiedColumnNames = (modified.getColumn('columnNames') || []);
var reset = (table.getRowCount() !== modifiedColumnNames.length);
if (!reset) {
for (var i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
if (columnNames[i] !== modifiedColumnNames[i]) {
reset = true;
break;
}
}
}
if (reset) {
return this.modifyTable(table, eventDetail);
}
for (var i = 0, i2 = rowIndex, iEnd = rows.length, row = void 0; i < iEnd; ++i, ++i2) {
row = rows[i];
if (row instanceof Array) {
modified.setColumn("".concat(i2), row);
}
else {
for (var j = 0, jEnd = columnNames.length; j < jEnd; ++j) {
modified.setCell("".concat(i2), j, row[columnNames[j]], eventDetail);
}
}
}
return table;
};
/**
* Inverts rows and columns in the table.
*
* @param {DataTable} table
* Table to invert.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {DataTable}
* Table with inverted `modified` property as a reference.
*/
InvertModifier.prototype.modifyTable = function (table, eventDetail) {
var modifier = this;
modifier.emit({ type: 'modify', detail: eventDetail, table: table });
var modified = table.modified;
if (table.hasColumns(['columnNames'])) { // inverted table
var columnNames = ((table.deleteColumns(['columnNames']) || {})
.columnNames || []).map(function (column) { return "".concat(column); }), columns = {};
for (var i = 0, iEnd = table.getRowCount(), row = void 0; i < iEnd; ++i) {
row = table.getRow(i);
if (row) {
columns[columnNames[i]] = row;
}
}
modified.deleteColumns();
modified.setColumns(columns);
}
else { // regular table
var columns = {};
for (var i = 0, iEnd = table.getRowCount(), row = void 0; i < iEnd; ++i) {
row = table.getRow(i);
if (row) {
columns["".concat(i)] = row;
}
}
columns.columnNames = table.getColumnNames();
modified.deleteColumns();
modified.setColumns(columns);
}
modifier.emit({ type: 'afterModify', detail: eventDetail, table: table });
return table;
};
/* *
*
* Static Properties
*
* */
/**
* Default options for the invert modifier.
*/
InvertModifier.defaultOptions = {
modifier: 'InvertModifier'
};
return InvertModifier;
}(DataModifier));
/* *
*
* Register
*
* */
DataModifier.addModifier(InvertModifier);
/* *
*
* Export
*
* */
export default InvertModifier;

View File

@@ -0,0 +1,145 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import DataModifier from './DataModifier.js';
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* *
*
* Class
*
* */
/**
* Filters out table rows with a specific value range.
*
* @private
*/
var RangeModifier = /** @class */ (function (_super) {
__extends(RangeModifier, _super);
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the range modifier.
*
* @param {RangeModifier.Options} [options]
* Options to configure the range modifier.
*/
function RangeModifier(options) {
var _this = _super.call(this) || this;
_this.options = merge(RangeModifier.defaultOptions, options);
return _this;
}
/* *
*
* Functions
*
* */
/**
* Replaces table rows with filtered rows.
*
* @param {DataTable} table
* Table to modify.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {DataTable}
* Table with `modified` property as a reference.
*/
RangeModifier.prototype.modifyTable = function (table, eventDetail) {
var modifier = this;
modifier.emit({ type: 'modify', detail: eventDetail, table: table });
var _a = modifier.options, ranges = _a.ranges, strict = _a.strict;
if (ranges.length) {
var columns = table.getColumns(), rows = [], modified = table.modified;
for (var i = 0, iEnd = ranges.length, range = void 0, rangeColumn = void 0; i < iEnd; ++i) {
range = ranges[i];
if (strict &&
typeof range.minValue !== typeof range.maxValue) {
continue;
}
rangeColumn = (columns[range.column] || []);
for (var j = 0, jEnd = rangeColumn.length, cell = void 0, row = void 0; j < jEnd; ++j) {
cell = rangeColumn[j];
switch (typeof cell) {
default:
continue;
case 'boolean':
case 'number':
case 'string':
break;
}
if (strict &&
typeof cell !== typeof range.minValue) {
continue;
}
if (cell >= range.minValue &&
cell <= range.maxValue) {
row = table.getRow(j);
if (row) {
rows.push(row);
}
}
}
}
modified.deleteRows();
modified.setRows(rows);
}
modifier.emit({ type: 'afterModify', detail: eventDetail, table: table });
return table;
};
/* *
*
* Static Properties
*
* */
/**
* Default options for the range modifier.
*/
RangeModifier.defaultOptions = {
modifier: 'Range',
strict: false,
ranges: []
};
return RangeModifier;
}(DataModifier));
/* *
*
* Register
*
* */
DataModifier.addModifier(RangeModifier);
/* *
*
* Export
*
* */
export default RangeModifier;

View File

@@ -0,0 +1,112 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Wojciech Chmiel
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import DataModifier from './DataModifier.js';
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* *
*
* Class
*
* */
/**
* @private
*/
var SeriesPointsModifier = /** @class */ (function (_super) {
__extends(SeriesPointsModifier, _super);
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the series points modifier.
*
* @param {SeriesPointsModifier.Options} [options]
* Options to configure the series points modifier.
*/
function SeriesPointsModifier(options) {
var _this = _super.call(this) || this;
_this.options = merge(SeriesPointsModifier.defaultOptions, options);
return _this;
}
/* *
*
* Functions
*
* */
/**
* Renames columns to alternative column names (alias) depending on mapping
* option.
*
* @param {DataTable} table
* Table to modify.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {DataTable}
* Table with `modified` property as a reference.
*/
SeriesPointsModifier.prototype.modifyTable = function (table, eventDetail) {
var modifier = this;
modifier.emit({ type: 'modify', detail: eventDetail, table: table });
var aliasMap = modifier.options.aliasMap || {}, aliases = Object.keys(aliasMap), modified = table.modified = table.clone(false, eventDetail);
for (var i = 0, iEnd = aliases.length, alias = void 0; i < iEnd; ++i) {
alias = aliases[i];
modified.renameColumn(aliasMap[alias], alias);
}
modifier.emit({ type: 'afterModify', detail: eventDetail, table: table });
return table;
};
/* *
*
* Static Properties
*
* */
/**
* Default options for the series points modifier.
*/
SeriesPointsModifier.defaultOptions = {
modifier: 'SeriesPoints'
};
return SeriesPointsModifier;
}(DataModifier));
/* *
*
* Register
*
* */
DataModifier.addModifier(SeriesPointsModifier);
/* *
*
* Export
*
* */
export default SeriesPointsModifier;

View File

@@ -0,0 +1,251 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import DataModifier from './DataModifier.js';
import DataTable from '../DataTable.js';
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* *
*
* Class
*
* */
/**
* Sort table rows according to values of a column.
*
* @private
*/
var SortModifier = /** @class */ (function (_super) {
__extends(SortModifier, _super);
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the range modifier.
*
* @param {RangeDataModifier.Options} [options]
* Options to configure the range modifier.
*/
function SortModifier(options) {
var _this = _super.call(this) || this;
_this.options = merge(SortModifier.defaultOptions, options);
return _this;
}
/* *
*
* Static Functions
*
* */
SortModifier.ascending = function (a, b) {
return ((a || 0) < (b || 0) ? -1 :
(a || 0) > (b || 0) ? 1 :
0);
};
SortModifier.descending = function (a, b) {
return ((b || 0) < (a || 0) ? -1 :
(b || 0) > (a || 0) ? 1 :
0);
};
/* *
*
* Functions
*
* */
/**
* Applies partial modifications of a cell change to the property `modified`
* of the given modified table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {string} columnName
* Column name of changed cell.
*
* @param {number|undefined} rowIndex
* Row index of changed cell.
*
* @param {Highcharts.DataTableCellType} cellValue
* Changed cell value.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
SortModifier.prototype.modifyCell = function (table, columnName, rowIndex, cellValue, eventDetail) {
var modifier = this, _a = modifier.options, orderByColumn = _a.orderByColumn, orderInColumn = _a.orderInColumn;
if (columnName === orderByColumn) {
if (orderInColumn) {
table.modified.setCell(columnName, rowIndex, cellValue);
table.modified.setColumn(orderInColumn, modifier
.modifyTable(new DataTable(table.getColumns([orderByColumn, orderInColumn])))
.modified
.getColumn(orderInColumn));
}
else {
modifier.modifyTable(table, eventDetail);
}
}
return table;
};
/**
* Applies partial modifications of column changes to the property
* `modified` of the given table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {Highcharts.DataTableColumnCollection} columns
* Changed columns as a collection, where the keys are the column names.
*
* @param {number} [rowIndex=0]
* Index of the first changed row.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
SortModifier.prototype.modifyColumns = function (table, columns, rowIndex, eventDetail) {
var modifier = this, _a = modifier.options, orderByColumn = _a.orderByColumn, orderInColumn = _a.orderInColumn, columnNames = Object.keys(columns);
if (columnNames.indexOf(orderByColumn) > -1) {
if (orderInColumn &&
columns[columnNames[0]].length) {
table.modified.setColumns(columns, rowIndex);
table.modified.setColumn(orderInColumn, modifier
.modifyTable(new DataTable(table.getColumns([orderByColumn, orderInColumn])))
.modified
.getColumn(orderInColumn));
}
else {
modifier.modifyTable(table, eventDetail);
}
}
return table;
};
/**
* Applies partial modifications of row changes to the property `modified`
* of the given table.
*
* @param {Highcharts.DataTable} table
* Modified table.
*
* @param {Array<(Highcharts.DataTableRow|Highcharts.DataTableRowObject)>} rows
* Changed rows.
*
* @param {number} [rowIndex]
* Index of the first changed row.
*
* @param {Highcharts.DataTableEventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {Highcharts.DataTable}
* Table with `modified` property as a reference.
*/
SortModifier.prototype.modifyRows = function (table, rows, rowIndex, eventDetail) {
var modifier = this, _a = modifier.options, orderByColumn = _a.orderByColumn, orderInColumn = _a.orderInColumn;
if (orderInColumn &&
rows.length) {
table.modified.setRows(rows, rowIndex);
table.modified.setColumn(orderInColumn, modifier
.modifyTable(new DataTable(table.getColumns([orderByColumn, orderInColumn])))
.modified
.getColumn(orderInColumn));
}
else {
modifier.modifyTable(table, eventDetail);
}
return table;
};
/**
* Sorts rows in the table.
*
* @param {DataTable} table
* Table to sort in.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {DataTable}
* Table with `modified` property as a reference.
*/
SortModifier.prototype.modifyTable = function (table, eventDetail) {
var _a;
var modifier = this;
modifier.emit({ type: 'modify', detail: eventDetail, table: table });
var columnNames = table.getColumnNames(), rowCount = table.getRowCount(), rowReferences = table.getRows().map(function (row, index) { return ({
index: index,
row: row
}); }), _b = modifier.options, direction = _b.direction, orderByColumn = _b.orderByColumn, orderInColumn = _b.orderInColumn, compare = (direction === 'asc' ?
SortModifier.ascending :
SortModifier.descending), orderByColumnIndex = columnNames.indexOf(orderByColumn), modified = table.modified;
if (orderByColumnIndex !== -1) {
rowReferences.sort(function (a, b) { return compare(a.row[orderByColumnIndex], b.row[orderByColumnIndex]); });
}
if (orderInColumn) {
var column = [];
for (var i = 0; i < rowCount; ++i) {
column[rowReferences[i].index] = i;
}
modified.setColumns((_a = {}, _a[orderInColumn] = column, _a));
}
else {
var rows = [];
for (var i = 0; i < rowCount; ++i) {
rows.push(rowReferences[i].row);
}
modified.setRows(rows, 0);
}
modifier.emit({ type: 'afterModify', detail: eventDetail, table: table });
return table;
};
/* *
*
* Static Properties
*
* */
/**
* Default options to group table rows.
*/
SortModifier.defaultOptions = {
modifier: 'Order',
direction: 'desc',
orderByColumn: 'y'
};
return SortModifier;
}(DataModifier));
/* *
*
* Default Export
*
* */
export default SortModifier;

View File

@@ -0,0 +1,402 @@
/* *
*
* (c) 2012-2021 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Torstein Hønsi
* - Christer Vasseng
* - Gøran Slettemark
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import DataParser from './DataParser.js';
import DataConverter from '../DataConverter.js';
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* eslint-disable no-invalid-this, require-jsdoc, valid-jsdoc */
/**
* Handles parsing and transforming CSV to a table.
*
* @private
*/
var CSVParser = /** @class */ (function (_super) {
__extends(CSVParser, _super);
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the CSV parser.
*
* @param {CSVParser.OptionsType} [options]
* Options for the CSV parser.
*
* @param {DataConverter} converter
* Parser data converter.
*/
function CSVParser(options, converter) {
var _this = _super.call(this) || this;
/* *
*
* Properties
*
* */
_this.columns = [];
_this.headers = [];
_this.dataTypes = [];
_this.options = merge(CSVParser.defaultOptions, options);
_this.converter = converter || new DataConverter();
return _this;
}
/**
* Initiates parsing of CSV
*
* @param {CSVParser.OptionsType}[options]
* Options for the parser
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @emits CSVDataParser#parse
* @emits CSVDataParser#afterParse
*/
CSVParser.prototype.parse = function (options, eventDetail) {
var parser = this, dataTypes = parser.dataTypes, converter = parser.converter, parserOptions = merge(this.options, options), beforeParse = parserOptions.beforeParse, lineDelimiter = parserOptions.lineDelimiter, firstRowAsNames = parserOptions.firstRowAsNames, itemDelimiter = parserOptions.itemDelimiter;
var lines, rowIt = 0, csv = parserOptions.csv, startRow = parserOptions.startRow, endRow = parserOptions.endRow, column;
parser.columns = [];
parser.emit({
type: 'parse',
columns: parser.columns,
detail: eventDetail,
headers: parser.headers
});
if (csv && beforeParse) {
csv = beforeParse(csv);
}
if (csv) {
lines = csv
.replace(/\r\n/g, '\n') // Unix
.replace(/\r/g, '\n') // Mac
.split(lineDelimiter || '\n');
if (!startRow || startRow < 0) {
startRow = 0;
}
if (!endRow || endRow >= lines.length) {
endRow = lines.length - 1;
}
if (!itemDelimiter) {
parser.guessedItemDelimiter = parser.guessDelimiter(lines);
}
// If the first row contain names, add them to the
// headers array and skip the row.
if (firstRowAsNames) {
var headers = lines[0]
.split(itemDelimiter || parser.guessedItemDelimiter || ',');
// Remove ""s from the headers
for (var i = 0; i < headers.length; i++) {
headers[i] = headers[i].replace(/^["']|["']$/g, '');
}
parser.headers = headers;
startRow++;
}
var offset = 0;
for (rowIt = startRow; rowIt <= endRow; rowIt++) {
if (lines[rowIt][0] === '#') {
offset++;
}
else {
parser.parseCSVRow(lines[rowIt], rowIt - startRow - offset);
}
}
if (dataTypes.length &&
dataTypes[0].length &&
dataTypes[0][1] === 'date' && // format is a string date
!parser.converter.getDateFormat()) {
parser.converter.deduceDateFormat(parser.columns[0], null, true);
}
// Guess types.
for (var i = 0, iEnd = parser.columns.length; i < iEnd; ++i) {
column = parser.columns[i];
for (var j = 0, jEnd = column.length; j < jEnd; ++j) {
if (column[j] && typeof column[j] === 'string') {
var cellValue = converter.asGuessedType(column[j]);
if (cellValue instanceof Date) {
cellValue = cellValue.getTime();
}
parser.columns[i][j] = cellValue;
}
}
}
}
parser.emit({
type: 'afterParse',
columns: parser.columns,
detail: eventDetail,
headers: parser.headers
});
};
/**
* Internal method that parses a single CSV row
*/
CSVParser.prototype.parseCSVRow = function (columnStr, rowNumber) {
var parser = this, converter = this.converter, columns = parser.columns || [], dataTypes = parser.dataTypes, _a = parser.options, startColumn = _a.startColumn, endColumn = _a.endColumn, itemDelimiter = (parser.options.itemDelimiter ||
parser.guessedItemDelimiter);
var decimalPoint = parser.options.decimalPoint;
if (!decimalPoint || decimalPoint === itemDelimiter) {
decimalPoint = parser.guessedDecimalPoint || '.';
}
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;
}
// Save the type of the token.
if (typeof token === 'string') {
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');
}
}
else {
pushType('number');
}
if (columns.length < column + 1) {
columns.push([]);
}
// Try to apply the decimal point, and check if the token then is a
// number. If not, reapply the initial value
if (typeof token !== 'number' &&
converter.guessType(token) !== 'number' &&
decimalPoint) {
var initialValue = token;
token = token.replace(decimalPoint, '.');
if (converter.guessType(token) !== 'number') {
token = initialValue;
}
}
columns[column][rowNumber] = token;
token = '';
++column;
++actualColumn;
}
if (!columnStr.trim().length) {
return;
}
if (columnStr.trim()[0] === '#') {
return;
}
for (; i < columnStr.length; i++) {
read(i);
if (c === '#') {
// If there are hexvalues remaining (#13283)
if (!/^#[0-F]{3,3}|[0-F]{6,6}/i.test(columnStr.substr(i))) {
// The rest of the row is a comment
push();
return;
}
}
// Quoted string
if (c === '"') {
read(++i);
while (i < columnStr.length) {
if (c === '"' && cl !== '"' && cn !== '"') {
break;
}
if (c !== '"' || (c === '"' && cl !== '"')) {
token += c;
}
read(++i);
}
}
else if (c === itemDelimiter) {
push();
// Actual column data
}
else {
token += c;
}
}
push();
};
/**
* Internal method that guesses the delimiter from the first
* 13 lines of the CSV
* @param {Array<string>} lines
* The CSV, split into lines
*/
CSVParser.prototype.guessDelimiter = function (lines) {
var points = 0, commas = 0, guessed;
var potDelimiters = {
',': 0,
';': 0,
'\t': 0
}, linesCount = lines.length;
for (var i = 0; i < linesCount; i++) {
var inStr = false, c = void 0, cn = void 0, cl = void 0, token = '';
// We should be able to detect dateformats within 13 rows
if (i > 13) {
break;
}
var columnStr = lines[i];
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
break;
}
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(Number(token)) ||
!isFinite(Number(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 (points > commas) {
this.guessedDecimalPoint = '.';
}
else {
this.guessedDecimalPoint = ',';
}
return guessed;
};
/**
* Handles converting the parsed data to a table.
*
* @return {DataTable}
* Table from the parsed CSV.
*/
CSVParser.prototype.getTable = function () {
return DataParser.getTableFromColumns(this.columns, this.headers);
};
/* *
*
* Static Properties
*
* */
/**
* Default options
*/
CSVParser.defaultOptions = __assign(__assign({}, DataParser.defaultOptions), { lineDelimiter: '\n' });
return CSVParser;
}(DataParser));
/* *
*
* Export
*
* */
export default CSVParser;

View File

@@ -0,0 +1,101 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
* - Sebastian Bochan
* - Gøran Slettemark
*
* */
'use strict';
import DataTable from '../DataTable.js';
import U from '../../Core/Utilities.js';
var addEvent = U.addEvent, fireEvent = U.fireEvent, uniqueKey = U.uniqueKey;
/* *
*
* Class
*
* */
/**
* Abstract class providing an interface and basic methods for a DataParser
*
* @private
*/
var DataParser = /** @class */ (function () {
function DataParser() {
}
/* *
*
* Static Functions
*
* */
/**
* Converts an array of columns to a table instance. Second dimension of the
* array are the row cells.
*
* @param {Array<DataTable.Column>} [columns]
* Array to convert.
*
* @param {Array<string>} [headers]
* Column names to use.
*
* @return {DataTable}
* Table instance from the arrays.
*/
DataParser.getTableFromColumns = function (columns, headers) {
if (columns === void 0) { columns = []; }
if (headers === void 0) { headers = []; }
var table = new DataTable();
for (var i = 0, iEnd = Math.max(headers.length, columns.length); i < iEnd; ++i) {
table.setColumn(headers[i] || "".concat(i), columns[i]);
}
return table;
};
/**
* Emits an event on the DataParser instance.
*
* @param {DataParser.Event} [e]
* Event object containing additional event data
*/
DataParser.prototype.emit = function (e) {
fireEvent(this, e.type, e);
};
/**
* Registers a callback for a specific parser event.
*
* @param {string} type
* Event type as a string.
*
* @param {DataEventEmitter.EventCallback} callback
* Function to register for an modifier callback.
*
* @return {Function}
* Function to unregister callback from the modifier event.
*/
DataParser.prototype.on = function (type, callback) {
return addEvent(this, type, callback);
};
/* *
*
* Static Properties
*
* */
/**
* Default options
*/
DataParser.defaultOptions = {
startColumn: 0,
endColumn: Number.MAX_VALUE,
startRow: 0,
endRow: Number.MAX_VALUE,
firstRowAsNames: true,
switchRowsAndColumns: false
};
return DataParser;
}());
export default DataParser;

View File

@@ -0,0 +1,224 @@
/* *
*
* (c) 2012-2021 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Torstein Hønsi
* - Gøran Slettemark
* - Wojciech Chmiel
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import DataParser from './DataParser.js';
import DataConverter from '../DataConverter.js';
import U from '../../Core/Utilities.js';
var merge = U.merge, uniqueKey = U.uniqueKey;
/* *
*
* Class
*
* */
/**
* Handles parsing and transformation of an Google Sheets to a table.
*
* @private
*/
var GoogleSheetsParser = /** @class */ (function (_super) {
__extends(GoogleSheetsParser, _super);
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the GoogleSheetsParser.
*
* @param {GoogleSheetsParser.OptionsType} [options]
* Options for the Google Sheets parser.
*
* @param {DataConverter} converter
* Parser data converter.
*/
function GoogleSheetsParser(options, converter) {
var _this = _super.call(this) || this;
_this.columns = [];
_this.headers = [];
_this.options = merge(GoogleSheetsParser.defaultOptions, options);
_this.converter = converter || new DataConverter();
return _this;
}
/* *
*
* Functions
*
* */
GoogleSheetsParser.prototype.getSheetColumns = function (json) {
var parser = this, _a = parser.options, startColumn = _a.startColumn, endColumn = _a.endColumn, startRow = _a.startRow, endRow = _a.endRow, columns = [], cells = json.feed.entry, cellCount = (cells || []).length;
var cell, colCount = 0, rowCount = 0, val, gr, gc, cellInner, i, j;
// 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 &&
cellInner.$t.indexOf('.') === -1)) {
// 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)
for (i = 0; i < colCount; i++) {
var column = columns[i];
// TODO: should this check be necessary?
if (column.length) {
for (i = 0; i < column.length; i++) {
if (typeof column[i] === 'undefined') {
column[i] = null;
}
}
}
}
return columns;
};
/**
* Initiates the parsing of the Google Sheet
*
* @param {GoogleSheetsParser.OptionsType}[options]
* Options for the parser
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @emits GoogleSheetsParser#parse
* @emits GoogleSheetsParser#afterParse
*/
GoogleSheetsParser.prototype.parse = function (jsonProp, eventDetail) {
var parser = this, parserOptions = merge(true, parser.options, { json: jsonProp }), converter = parser.converter, json = parserOptions.json, cells = json.feed.entry, headers = parser.headers;
var column;
if (!cells || cells.length === 0) {
return false;
}
parser.headers = [];
parser.columns = [];
parser.emit({
type: 'parse',
columns: parser.columns,
detail: eventDetail,
headers: parser.headers
});
parser.columns = parser.getSheetColumns(json);
for (var i = 0, iEnd = parser.columns.length; i < iEnd; i++) {
column = parser.columns[i];
parser.headers[i] = parserOptions.firstRowAsNames ?
column.splice(0, 1).toString() :
uniqueKey();
for (var j = 0, jEnd = column.length; j < jEnd; ++j) {
if (column[j] && typeof column[j] === 'string') {
var cellValue = converter.asGuessedType(column[j]);
if (cellValue instanceof Date) {
cellValue = cellValue.getTime();
}
parser.columns[i][j] = cellValue;
}
}
}
parser.emit({
type: 'afterParse',
columns: parser.columns,
detail: eventDetail,
headers: parser.headers
});
};
/**
* Handles converting the parsed data to a table.
*
* @return {DataTable}
* Table from the parsed Google Sheet
*/
GoogleSheetsParser.prototype.getTable = function () {
return DataParser.getTableFromColumns(this.columns, this.headers);
};
/* *
*
* Static Properties
*
* */
/**
* Default options
*/
GoogleSheetsParser.defaultOptions = __assign(__assign({}, DataParser.defaultOptions), { json: {} });
return GoogleSheetsParser;
}(DataParser));
/* *
*
* Export
*
* */
export default GoogleSheetsParser;

View File

@@ -0,0 +1,215 @@
/* *
*
* (c) 2012-2021 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Torstein Hønsi
* - Gøran Slettemark
* - Wojciech Chmiel
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import DataParser from './DataParser.js';
import DataConverter from '../DataConverter.js';
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* *
*
* Class
*
* */
/**
* Handles parsing and transformation of an HTML table to a table.
*
* @private
*/
var HTMLTableParser = /** @class */ (function (_super) {
__extends(HTMLTableParser, _super);
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of the HTML table parser.
*
* @param {HTMLTableParser.OptionsType} [options]
* Options for the CSV parser.
*
* @param {HTMLElement | null} tableElement
* The HTML table to parse
*
* @param {DataConverter} converter
* Parser data converter.
*/
function HTMLTableParser(options, tableElement, converter) {
if (tableElement === void 0) { tableElement = null; }
var _this = _super.call(this) || this;
_this.columns = [];
_this.headers = [];
_this.options = merge(HTMLTableParser.defaultOptions, options);
_this.converter = converter || new DataConverter();
if (tableElement) {
_this.tableElement = tableElement;
_this.tableElementID = tableElement.id;
}
else if (options && options.tableHTML) {
_this.tableElement = options.tableHTML;
_this.tableElementID = options.tableHTML.id;
}
return _this;
}
/* *
*
* Functions
*
* */
/**
* Initiates the parsing of the HTML table
*
* @param {HTMLTableParser.OptionsType}[options]
* Options for the parser
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @emits CSVDataParser#parse
* @emits CSVDataParser#afterParse
* @emits HTMLTableParser#parseError
*/
HTMLTableParser.prototype.parse = function (options, eventDetail) {
var parser = this, converter = this.converter, columns = [], headers = [], parseOptions = merge(parser.options, options), endRow = parseOptions.endRow, startColumn = parseOptions.startColumn, endColumn = parseOptions.endColumn, firstRowAsNames = parseOptions.firstRowAsNames, tableHTML = parseOptions.tableHTML || this.tableElement;
if (!(tableHTML instanceof HTMLElement)) {
parser.emit({
type: 'parseError',
columns: columns,
detail: eventDetail,
headers: headers,
error: 'Not a valid HTML Table'
});
return;
}
parser.tableElement = this.tableElement;
parser.tableElementID = tableHTML.id;
this.emit({
type: 'parse',
columns: parser.columns,
detail: eventDetail,
headers: parser.headers
});
var rows = tableHTML.getElementsByTagName('tr'), rowsCount = rows.length;
var rowIndex = 0, item, startRow = parseOptions.startRow;
// Insert headers from the first row
if (firstRowAsNames && rowsCount) {
var items = rows[0].children, itemsLength = items.length;
for (var i = startColumn; i < itemsLength; i++) {
if (i > endColumn) {
break;
}
item = items[i];
if (item.tagName === 'TD' ||
item.tagName === 'TH') {
headers.push(item.innerHTML);
}
}
startRow++;
}
while (rowIndex < rowsCount) {
if (rowIndex >= startRow && rowIndex <= endRow) {
var columnsInRow = rows[rowIndex].children, columnsInRowLength = columnsInRow.length;
var columnIndex = 0;
while (columnIndex < columnsInRowLength) {
var relativeColumnIndex = columnIndex - startColumn, row = columns[relativeColumnIndex];
item = columnsInRow[columnIndex];
if ((item.tagName === 'TD' ||
item.tagName === 'TH') &&
(columnIndex >= startColumn &&
columnIndex <= endColumn)) {
if (!columns[relativeColumnIndex]) {
columns[relativeColumnIndex] = [];
}
var cellValue = converter.asGuessedType(item.innerHTML);
if (cellValue instanceof Date) {
cellValue = cellValue.getTime();
}
columns[relativeColumnIndex][rowIndex - startRow] = cellValue;
// Loop over all previous indices and make sure
// they are nulls, not undefined.
var i = 1;
while (rowIndex - startRow >= i &&
row[rowIndex - startRow - i] === void 0) {
row[rowIndex - startRow - i] = null;
i++;
}
}
columnIndex++;
}
}
rowIndex++;
}
this.columns = columns;
this.headers = headers;
this.emit({
type: 'afterParse',
columns: columns,
detail: eventDetail,
headers: headers
});
};
/**
* Handles converting the parsed data to a table.
*
* @return {DataTable}
* Table from the parsed HTML table
*/
HTMLTableParser.prototype.getTable = function () {
return DataParser.getTableFromColumns(this.columns, this.headers);
};
/* *
*
* Static Properties
*
* */
/**
* Default options
*/
HTMLTableParser.defaultOptions = __assign({}, DataParser.defaultOptions);
return HTMLTableParser;
}(DataParser));
/* *
*
* Export
*
* */
export default HTMLTableParser;

View File

@@ -0,0 +1,320 @@
/* *
*
* (c) 2012-2021 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Torstein Hønsi
* - Christer Vasseng
* - Gøran Slettemark
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import CSVParser from '../Parsers/CSVParser.js';
import DataStore from './DataStore.js';
import DataTable from '../DataTable.js';
import HU from '../../Core/HttpUtilities.js';
var ajax = HU.ajax;
import U from '../../Core/Utilities.js';
var merge = U.merge, objectEach = U.objectEach;
/* *
*
* Class
*
* */
/* eslint-disable no-invalid-this, require-jsdoc, valid-jsdoc */
/**
* Class that handles creating a datastore from CSV
*
* @private
*/
var CSVStore = /** @class */ (function (_super) {
__extends(CSVStore, _super);
/* *
*
* Constructors
*
* */
/**
* Constructs an instance of CSVDataStore.
*
* @param {DataTable} table
* Optional table to create the store from.
*
* @param {CSVStore.OptionsType} options
* Options for the store and parser.
*
* @param {DataParser} parser
* Optional parser to replace the default parser.
*/
function CSVStore(table, options, parser) {
if (table === void 0) { table = new DataTable(); }
if (options === void 0) { options = {}; }
var _this = _super.call(this, table) || this;
var csv = options.csv, csvURL = options.csvURL, enablePolling = options.enablePolling, dataRefreshRate = options.dataRefreshRate, parserOptions = __rest(options, ["csv", "csvURL", "enablePolling", "dataRefreshRate"]);
_this.parserOptions = parserOptions;
_this.options = merge(CSVStore.defaultOptions, { csv: csv, csvURL: csvURL, enablePolling: enablePolling, dataRefreshRate: dataRefreshRate });
_this.parser = parser || new CSVParser(parserOptions);
return _this;
}
/**
* Handles polling of live data
*/
CSVStore.prototype.poll = function () {
var _this = this;
var _a = this.options, dataRefreshRate = _a.dataRefreshRate, enablePolling = _a.enablePolling, csvURL = _a.csvURL;
var updateIntervalMs = (dataRefreshRate > 1 ? dataRefreshRate : 1) * 1000;
if (enablePolling && csvURL === this.liveDataURL) {
// We need to stop doing this if the URL has changed
this.liveDataTimeout = setTimeout(function () {
_this.fetchCSV();
}, updateIntervalMs);
}
};
/**
* Fetches CSV from external source
*
* @param {boolean} initialFetch
* Indicates whether this is a single fetch or a repeated fetch
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @emits CSVDataStore#load
* @emits CSVDataStore#afterLoad
* @emits CSVDataStore#loadError
*/
CSVStore.prototype.fetchCSV = function (initialFetch, eventDetail) {
var store = this, maxRetries = 3, csvURL = store.options.csvURL;
var currentRetries;
// Clear the table
store.table.deleteColumns();
if (initialFetch) {
clearTimeout(store.liveDataTimeout);
store.liveDataURL = csvURL;
}
store.emit({ type: 'load', detail: eventDetail, table: store.table });
ajax({
url: store.liveDataURL || '',
dataType: 'text',
success: function (csv) {
csv = "".concat(csv);
store.parser.parse({ csv: csv });
// On inital fetch we need to set the columns
store.table.setColumns(store.parser.getTable().getColumns());
if (store.liveDataURL) {
store.poll();
}
store.emit({
type: 'afterLoad',
csv: csv,
detail: eventDetail,
table: store.table
});
},
error: function (xhr, error) {
if (++currentRetries < maxRetries) {
store.poll();
}
store.emit({
type: 'loadError',
detail: eventDetail,
error: error,
table: store.table,
xhr: xhr
});
}
});
};
/**
* Initiates the loading of the CSV source to the store
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @emits CSVParser#load
* @emits CSVParser#afterLoad
*/
CSVStore.prototype.load = function (eventDetail) {
var store = this, parser = store.parser, table = store.table, _a = store.options, csv = _a.csv, csvURL = _a.csvURL;
if (csv) {
// If already loaded, clear the current rows
table.deleteRows();
store.emit({
type: 'load',
csv: csv,
detail: eventDetail,
table: table
});
parser.parse({ csv: csv });
table.setColumns(parser.getTable().getColumns());
store.emit({
type: 'afterLoad',
csv: csv,
detail: eventDetail,
table: table
});
}
else if (csvURL) {
store.fetchCSV(true, eventDetail);
}
else {
store.emit({
type: 'loadError',
detail: eventDetail,
error: 'Unable to load: no CSV string or URL was provided',
table: table
});
}
};
/**
* Creates a CSV string from the datatable on the store instance.
*
* @param {CSVStore.ExportOptions} exportOptions
* The options used for the export.
*
* @return {string}
* A CSV string from the table.
*/
CSVStore.prototype.getCSVForExport = function (exportOptions) {
var useLocalDecimalPoint = exportOptions.useLocalDecimalPoint, lineDelimiter = exportOptions.lineDelimiter, exportNames = (this.parserOptions.firstRowAsNames !== false);
var decimalPoint = exportOptions.decimalPoint, itemDelimiter = exportOptions.itemDelimiter;
if (!decimalPoint) {
decimalPoint = itemDelimiter !== ',' && useLocalDecimalPoint ?
(1.1).toLocaleString()[1] :
'.';
}
if (!itemDelimiter) {
itemDelimiter = decimalPoint === ',' ? ';' : ',';
}
var _a = this.getColumnsForExport(exportOptions.usePresentationOrder), columnNames = _a.columnNames, columnValues = _a.columnValues;
var csvRows = [], columnsCount = columnNames.length;
var rowArray = [];
// Add the names as the first row if they should be exported
if (exportNames) {
csvRows.push(columnNames.map(function (columnName) { return "\"".concat(columnName, "\""); }).join(itemDelimiter));
}
for (var columnIndex = 0; columnIndex < columnsCount; columnIndex++) {
var columnName = columnNames[columnIndex], column = columnValues[columnIndex], columnLength = column.length;
var columnMeta = this.whatIs(columnName);
var columnDataType = void 0;
if (columnMeta) {
columnDataType = columnMeta.dataType;
}
for (var rowIndex = 0; rowIndex < columnLength; rowIndex++) {
var cellValue = column[rowIndex];
if (!rowArray[rowIndex]) {
rowArray[rowIndex] = [];
}
// Prefer datatype from metadata
if (columnDataType === 'string') {
cellValue = "\"".concat(cellValue, "\"");
}
else if (typeof cellValue === 'number') {
cellValue = String(cellValue).replace('.', decimalPoint);
}
else if (typeof cellValue === 'string') {
cellValue = "\"".concat(cellValue, "\"");
}
rowArray[rowIndex][columnIndex] = cellValue;
// On the final column, push the row to the CSV
if (columnIndex === columnsCount - 1) {
// Trim repeated undefined values starting at the end
// Currently, we export the first "comma" even if the
// second value is undefined
var i = columnIndex;
while (rowArray[rowIndex].length > 2) {
var cellVal = rowArray[rowIndex][i];
if (cellVal !== void 0) {
break;
}
rowArray[rowIndex].pop();
i--;
}
csvRows.push(rowArray[rowIndex].join(itemDelimiter));
}
}
}
return csvRows.join(lineDelimiter);
};
/**
* Exports the datastore as a CSV string, using the options
* provided on import unless other options are provided.
*
* @param {CSVStore.ExportOptions} [csvExportOptions]
* Options to use instead of those used on import.
*
* @return {string}
* CSV from the store's current table.
*
*/
CSVStore.prototype.save = function (csvExportOptions) {
var exportOptions = CSVStore.defaultExportOptions;
// Merge in the provided parser options
objectEach(this.parserOptions, function (value, key) {
if (key in exportOptions) {
exportOptions[key] = value;
}
});
return this.getCSVForExport(merge(exportOptions, csvExportOptions));
};
/* *
*
* Static Properties
*
* */
CSVStore.defaultOptions = {
csv: '',
csvURL: '',
enablePolling: false,
dataRefreshRate: 1
};
CSVStore.defaultExportOptions = {
decimalPoint: null,
itemDelimiter: null,
lineDelimiter: '\n'
};
return CSVStore;
}(DataStore));
/* *
*
* Registry
*
* */
DataStore.addStore(CSVStore);
/* *
*
* Export
*
* */
export default CSVStore;

View File

@@ -0,0 +1,276 @@
/* *
*
* (c) 2020-2022 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Sophie Bremer
* - Wojciech Chmiel
* - Gøran Slettemark
*
* */
'use strict';
import DataTable from '../DataTable.js';
import U from '../../Core/Utilities.js';
var addEvent = U.addEvent, fireEvent = U.fireEvent, merge = U.merge, pick = U.pick;
/* *
*
* Class
*
* */
/**
* Abstract class providing an interface for managing a DataStore.
*
* @private
*/
var DataStore = /** @class */ (function () {
/* *
*
* Constructor
*
* */
/**
* Constructor for the store class.
*
* @param {DataTable} table
* Optional table to use in the store.
*
* @param {DataStore.Metadata} metadata
* Optional metadata to use in the store.
*/
function DataStore(table, metadata) {
if (table === void 0) { table = new DataTable(); }
if (metadata === void 0) { metadata = { columns: {} }; }
this.table = table;
this.metadata = metadata;
}
/* *
*
* Static Functions
*
* */
/**
* Adds a store class to the registry. The store has to provide the
* `DataStore.options` property and the `DataStore.load` method to
* modify the table.
*
* @param {DataStore} dataStore
* Store class (aka class constructor) to register.
*
* @return {boolean}
* Returns true, if the registration was successful. False is returned, if
* their is already a store registered with this name.
*/
DataStore.addStore = function (dataStore) {
var name = DataStore.getName(dataStore), registry = DataStore.registry;
if (typeof name === 'undefined' ||
registry[name]) {
return false;
}
registry[name] = dataStore;
return true;
};
/**
* Returns all registered dataStore names.
*
* @return {Array<string>}
* All registered store names.
*/
DataStore.getAllStoreNames = function () {
return Object.keys(DataStore.registry);
};
/**
* Returns a copy of the dataStore registry as record object with
* dataStore names and their dataStore class.
*
* @return {Record<string,DataStoreRegistryType>}
* Copy of the dataStore registry.
*/
DataStore.getAllStores = function () {
return merge(DataStore.registry);
};
/**
* Extracts the name from a given dataStore class.
*
* @param {DataStore} dataStore
* DataStore class to extract the name from.
*
* @return {string}
* DataStore name, if the extraction was successful, otherwise an empty
* string.
*/
DataStore.getName = function (dataStore) {
return (dataStore.toString().match(DataStore.nameRegExp) ||
['', ''])[1];
};
/**
* Returns a dataStore class (aka class constructor) of the given dataStore
* name.
*
* @param {string} name
* Registered class name of the class type.
*
* @return {DataStoreRegistryType|undefined}
* Class type, if the class name was found, otherwise `undefined`.
*/
DataStore.getStore = function (name) {
return DataStore.registry[name];
};
/* *
*
* Functions
*
* */
/**
* Method for adding metadata for a single column.
*
* @param {string} name
* The name of the column to be described.
*
* @param {DataStore.MetaColumn} columnMeta
* The metadata to apply to the column.
*/
DataStore.prototype.describeColumn = function (name, columnMeta) {
var store = this, columns = store.metadata.columns;
columns[name] = merge(columns[name] || {}, columnMeta);
};
/**
* Method for applying columns meta information to the whole datastore.
*
* @param {Record<string, DataStore.MetaColumn>} columns
* Pairs of column names and MetaColumn objects.
*/
DataStore.prototype.describeColumns = function (columns) {
var store = this, columnNames = Object.keys(columns);
var columnName;
while (typeof (columnName = columnNames.pop()) === 'string') {
store.describeColumn(columnName, columns[columnName]);
}
};
/**
* Emits an event on the store to all registered callbacks of this event.
*
* @param {DataStore.Event} [e]
* Event object containing additional event information.
*/
DataStore.prototype.emit = function (e) {
fireEvent(this, e.type, e);
};
/**
* Returns the order of columns.
*
* @param {boolean} [usePresentationState]
* Whether to use the column order of the presentation state of the table.
*
* @return {Array<string>}
* Order of columns.
*/
DataStore.prototype.getColumnOrder = function (usePresentationState) {
var store = this, metadata = store.metadata, columns = metadata.columns, columnNames = Object.keys(columns), columnOrder = [];
var columnName;
for (var i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
columnName = columnNames[i];
columnOrder[pick(columns[columnName].index, i)] = columnName;
}
return columnOrder;
};
/**
* Retrieves the columns of the the dataTable,
* applies column order from meta.
*
* @param {boolean} [usePresentationOrder]
* Whether to use the column order of the presentation state of the table.
*
* @return {{}}
* An object with the properties `columnNames` and `columnValues`
*/
DataStore.prototype.getColumnsForExport = function (usePresentationOrder) {
var table = this.table, columnsRecord = table.getColumns(), columnNames = table.getColumnNames();
var columnOrder = this.getColumnOrder(usePresentationOrder);
if (columnOrder.length) {
columnNames.sort(function (a, b) {
if (columnOrder.indexOf(a) < columnOrder.indexOf(b)) {
return 1;
}
if (columnOrder.indexOf(a) > columnOrder.indexOf(b)) {
return -1;
}
return 0;
});
}
return ({
columnNames: columnNames,
columnValues: columnNames.map(function (name) { return columnsRecord[name]; })
});
};
/**
* The default load method, which fires the `afterLoad` event
* @emits DataStore#afterLoad
*/
DataStore.prototype.load = function () {
fireEvent(this, 'afterLoad', { table: this.table });
};
/**
* Registers a callback for a specific store event.
*
* @param {string} type
* Event type as a string.
*
* @param {DataEventEmitter.EventCallback} callback
* Function to register for the store callback.
*
* @return {Function}
* Function to unregister callback from the store event.
*/
DataStore.prototype.on = function (type, callback) {
return addEvent(this, type, callback);
};
/**
* Sets the index and order of columns.
*
* @param {Array<string>} columnNames
* Order of columns.
*/
DataStore.prototype.setColumnOrder = function (columnNames) {
var store = this;
for (var i = 0, iEnd = columnNames.length; i < iEnd; ++i) {
store.describeColumn(columnNames[i], { index: i });
}
};
/**
* Method for retriving metadata from a single column.
*
* @param {string} name
* The identifier for the column that should be described
*
* @return {DataStore.MetaColumn | undefined}
* Returns a MetaColumn object if found.
*/
DataStore.prototype.whatIs = function (name) {
return this.metadata.columns[name];
};
/* *
*
* Static Properties
*
* */
/**
* Registry as a record object with store names and their class.
*/
DataStore.registry = {};
/**
* Regular expression to extract the store name (group 1) from the
* stringified class type.
*/
DataStore.nameRegExp = (/^function\s+(\w*?)(?:DataStore)?\s*\(/);
return DataStore;
}());
/* *
*
* Export
*
* */
export default DataStore;

View File

@@ -0,0 +1,171 @@
/* *
*
* (c) 2012-2021 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Torstein Hønsi
* - Gøran Slettemark
* - Wojciech Chmiel
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import DataStore from './DataStore.js';
import GoogleSheetsParser from '../Parsers/GoogleSheetsParser.js';
import HU from '../../Core/HttpUtilities.js';
var ajax = HU.ajax;
import U from '../../Core/Utilities.js';
var merge = U.merge;
/* *
*
* Class
*
* *7
/* eslint-disable no-invalid-this, require-jsdoc, valid-jsdoc */
/**
* @private
*/
var GoogleSheetsStore = /** @class */ (function (_super) {
__extends(GoogleSheetsStore, _super);
/* *
*
* Constructor
*
* */
/**
* Constructs an instance of GoogleSheetsStore
*
* @param {DataTable} table
* Optional table to create the store from.
*
* @param {CSVStore.OptionsType} options
* Options for the store and parser.
*
* @param {DataParser} parser
* Optional parser to replace the default parser
*/
function GoogleSheetsStore(table, options, parser) {
var _this = _super.call(this, table) || this;
_this.options = merge(GoogleSheetsStore.defaultOptions, options);
_this.parser = parser || new GoogleSheetsParser({
firstRowAsNames: _this.options.firstRowAsNames
});
return _this;
}
/* *
*
* Functions
*
* */
/**
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*/
GoogleSheetsStore.prototype.fetchSheet = function (eventDetail) {
var store = this, _a = store.options, enablePolling = _a.enablePolling, dataRefreshRate = _a.dataRefreshRate, googleSpreadsheetKey = _a.googleSpreadsheetKey, worksheet = _a.worksheet, url = [
'https://spreadsheets.google.com/feeds/cells',
googleSpreadsheetKey,
worksheet,
'public/values?alt=json'
].join('/');
// If already loaded, clear the current table
store.table.deleteColumns();
store.emit({
type: 'load',
detail: eventDetail,
table: store.table,
url: url
});
ajax({
url: url,
dataType: 'json',
success: function (json) {
store.parser.parse(json);
store.table.setColumns(store.parser.getTable().getColumns());
// Polling
if (enablePolling) {
setTimeout(function () {
store.fetchSheet();
}, dataRefreshRate * 1000);
}
store.emit({
type: 'afterLoad',
detail: eventDetail,
table: store.table,
url: url
});
},
error: function (xhr, error) {
/* *
* TODO:
* catch error
* ...
*
* */
// console.log(text);
store.emit({
type: 'loadError',
detail: eventDetail,
error: error,
table: store.table,
xhr: xhr
});
}
});
// return true;
};
/**
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*/
GoogleSheetsStore.prototype.load = function (eventDetail) {
if (this.options.googleSpreadsheetKey) {
this.fetchSheet(eventDetail);
}
};
/* *
*
* Static Properties
*
* */
GoogleSheetsStore.defaultOptions = {
googleSpreadsheetKey: '',
worksheet: 1,
enablePolling: false,
dataRefreshRate: 2,
firstRowAsNames: true
};
return GoogleSheetsStore;
}(DataStore));
/* *
*
* Registry
*
* */
DataStore.addStore(GoogleSheetsStore);
/* *
*
* Export
*
* */
export default GoogleSheetsStore;

View File

@@ -0,0 +1,355 @@
/* *
*
* (c) 2012-2021 Highsoft AS
*
* License: www.highcharts.com/license
*
* !!!!!!! SOURCE GETS TRANSPILED BY TYPESCRIPT. EDIT TS FILE ONLY. !!!!!!!
*
* Authors:
* - Torstein Hønsi
* - Gøran Slettemark
* - Wojciech Chmiel
* - Sophie Bremer
*
* */
'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 (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
import DataStore from './DataStore.js';
import DataTable from '../DataTable.js';
import H from '../../Core/Globals.js';
var win = H.win;
import HTMLTableParser from '../Parsers/HTMLTableParser.js';
import U from '../../Core/Utilities.js';
var merge = U.merge, objectEach = U.objectEach;
/** eslint-disable valid-jsdoc */
/**
* Class that handles creating a datastore from an HTML table
*
* @private
*/
var HTMLTableStore = /** @class */ (function (_super) {
__extends(HTMLTableStore, _super);
/* *
*
* Constructors
*
* */
/**
* Constructs an instance of HTMLTableDataStore
*
* @param {DataTable} table
* Optional table to create the store from
*
* @param {HTMLTableStore.OptionsType} options
* Options for the store and parser
*
* @param {DataParser} parser
* Optional parser to replace the default parser
*/
function HTMLTableStore(table, options, parser) {
if (table === void 0) { table = new DataTable(); }
if (options === void 0) { options = {}; }
var _this = _super.call(this, table) || this;
_this.tableElement = null;
_this.options = merge(HTMLTableStore.defaultOptions, options);
_this.parserOptions = _this.options;
_this.parser = parser || new HTMLTableParser(_this.options, _this.tableElement);
return _this;
}
/**
* Handles retrieving the HTML table by ID if an ID is provided
*/
HTMLTableStore.prototype.fetchTable = function () {
var store = this, tableHTML = store.options.table;
var tableElement;
if (typeof tableHTML === 'string') {
store.tableID = tableHTML;
tableElement = win.document.getElementById(tableHTML);
}
else {
tableElement = tableHTML;
store.tableID = tableElement.id;
}
store.tableElement = tableElement;
};
/**
* Initiates creating the datastore from the HTML table
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @emits HTMLTableDataStore#load
* @emits HTMLTableDataStore#afterLoad
* @emits HTMLTableDataStore#loadError
*/
HTMLTableStore.prototype.load = function (eventDetail) {
var store = this;
store.fetchTable();
// If already loaded, clear the current rows
store.table.deleteColumns();
store.emit({
type: 'load',
detail: eventDetail,
table: store.table,
tableElement: store.tableElement
});
if (!store.tableElement) {
store.emit({
type: 'loadError',
detail: eventDetail,
error: 'HTML table not provided, or element with ID not found',
table: store.table
});
return;
}
store.parser.parse(merge({ tableHTML: store.tableElement }, store.options), eventDetail);
store.table.setColumns(store.parser.getTable().getColumns());
store.emit({
type: 'afterLoad',
detail: eventDetail,
table: store.table,
tableElement: store.tableElement
});
};
/**
* Creates an HTML table from the datatable on the store instance.
*
* @param {HTMLTableStore.ExportOptions} [exportOptions]
* Options used for exporting.
*
* @return {string}
* The HTML table.
*/
HTMLTableStore.prototype.getHTMLTableForExport = function (exportOptions) {
if (exportOptions === void 0) { exportOptions = {}; }
var options = exportOptions, decimalPoint = options.useLocalDecimalPoint ?
(1.1).toLocaleString()[1] :
'.', exportNames = (this.parserOptions.firstRowAsNames !== false), useMultiLevelHeaders = options.useMultiLevelHeaders, useRowspanHeaders = options.useRowspanHeaders;
var 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 header markup from row data
var getTableHeaderHTML = function (topheaders, subheaders, rowLength) {
var html = '<thead>', 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 += '<tr>';
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 (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 += '</tr>';
}
// Add the subheaders (the only headers if not using multilevels)
if (subheaders) {
html += '<tr>';
for (i = 0, len = subheaders.length; i < len; ++i) {
if (typeof subheaders[i] !== 'undefined') {
html += getCellHTMLFromValue('th', null, 'scope="col"', subheaders[i]);
}
}
html += '</tr>';
}
html += '</thead>';
return html;
};
var getCellHTMLFromValue = function (tag, classes, attrs, value) {
var val = 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) {
val = '';
className = 'empty';
}
return '<' + tag + (attrs ? ' ' + attrs : '') +
' class="' + className + '">' +
val + '</' + tag + '>';
};
var _a = this.getColumnsForExport(options.usePresentationOrder), columnNames = _a.columnNames, columnValues = _a.columnValues, htmlRows = [], columnsCount = columnNames.length;
var rowArray = [];
var tableHead = '';
// Add the names as the first row if they should be exported
if (exportNames) {
var subcategories_1 = [];
// If using multilevel headers, the first value
// of each column is a subcategory
if (useMultiLevelHeaders) {
columnValues.forEach(function (column) {
var subhead = (column.shift() || '').toString();
subcategories_1.push(subhead);
});
tableHead = getTableHeaderHTML(columnNames, subcategories_1);
}
else {
tableHead = getTableHeaderHTML(null, columnNames);
}
}
for (var columnIndex = 0; columnIndex < columnsCount; columnIndex++) {
var columnName = columnNames[columnIndex], column = columnValues[columnIndex], columnLength = column.length;
var columnMeta = this.whatIs(columnName);
var columnDataType = void 0;
if (columnMeta) {
columnDataType = columnMeta.dataType;
}
for (var rowIndex = 0; rowIndex < columnLength; rowIndex++) {
var cellValue = column[rowIndex];
if (!rowArray[rowIndex]) {
rowArray[rowIndex] = [];
}
// Handle datatype
// if(columnDataType && typeof cellValue !== columnDataType) {
// do something?
// }
if (!(typeof cellValue === 'string' ||
typeof cellValue === 'number' ||
typeof cellValue === 'undefined')) {
cellValue = (cellValue || '').toString();
}
rowArray[rowIndex][columnIndex] = getCellHTMLFromValue(columnIndex ? 'td' : 'th', null, columnIndex ? '' : 'scope="row"', cellValue);
// On the final column, push the row to the array
if (columnIndex === columnsCount - 1) {
htmlRows.push('<tr>' +
rowArray[rowIndex].join('') +
'</tr>');
}
}
}
var caption = '';
// Add table caption
// Current exportdata falls back to chart title
// but that should probably be handled elsewhere?
if (options.tableCaption) {
caption = '<caption class="highcharts-table-caption">' +
options.tableCaption +
'</caption>';
}
return ('<table>' +
caption +
tableHead +
'<tbody>' +
htmlRows.join('') +
'</tbody>' +
'</table>');
};
/**
* Exports the datastore as an HTML string, using the options
* provided on import unless other options are provided.
*
* @param {HTMLTableStore.ExportOptions} [htmlExportOptions]
* Options that override default or existing export options.
*
* @param {DataEventEmitter.EventDetail} [eventDetail]
* Custom information for pending events.
*
* @return {string}
* HTML from the current dataTable.
*
*/
HTMLTableStore.prototype.save = function (htmlExportOptions, eventDetail) {
var exportOptions = HTMLTableStore.defaultExportOptions;
// Merge in the provided parser options
objectEach(this.parserOptions, function (value, key) {
if (key in exportOptions) {
exportOptions[key] = value;
}
});
// Merge in provided options
return this.getHTMLTableForExport(merge(exportOptions, htmlExportOptions));
};
/* *
*
* Static Properties
*
* */
HTMLTableStore.defaultOptions = {
table: ''
};
HTMLTableStore.defaultExportOptions = {
decimalPoint: null,
exportIDColumn: false,
useRowspanHeaders: true,
useMultiLevelHeaders: true
};
return HTMLTableStore;
}(DataStore));
/* *
*
* Register
*
* */
DataStore.addStore(HTMLTableStore);
/* *
*
* Export
*
* */
export default HTMLTableStore;