mirror of
https://github.com/chartjs/Chart.js.git
synced 2025-12-08 20:36:08 +00:00
[perf] Update/draw only visible line/points (#7793)
* Restore count parameter to updateElements * [perf] Update/draw only visible line/points * CC
This commit is contained in:
parent
17e27e16cc
commit
8cdc60ccd1
@ -461,7 +461,7 @@ The APIs listed in this section have changed in signature or behaviour from vers
|
||||
|
||||
##### Dataset Controllers
|
||||
|
||||
* `updateElement` was replaced with `updateElements` now taking the elements to update, the `start` index, and `mode`
|
||||
* `updateElement` was replaced with `updateElements` now taking the elements to update, the `start` index, `count`, and `mode`
|
||||
* `setHoverStyle` and `removeHoverStyle` now additionally take the `datasetIndex` and `index`
|
||||
|
||||
#### Interactions
|
||||
|
||||
@ -231,10 +231,10 @@ export default class BarController extends DatasetController {
|
||||
const me = this;
|
||||
const meta = me._cachedMeta;
|
||||
|
||||
me.updateElements(meta.data, 0, mode);
|
||||
me.updateElements(meta.data, 0, meta.data.length, mode);
|
||||
}
|
||||
|
||||
updateElements(rectangles, start, mode) {
|
||||
updateElements(rectangles, start, count, mode) {
|
||||
const me = this;
|
||||
const reset = mode === 'reset';
|
||||
const vscale = me._cachedMeta.vScale;
|
||||
@ -247,11 +247,10 @@ export default class BarController extends DatasetController {
|
||||
|
||||
me.updateSharedOptions(sharedOptions, mode, firstOpts);
|
||||
|
||||
for (let i = 0; i < rectangles.length; i++) {
|
||||
const index = start + i;
|
||||
const options = sharedOptions || me.resolveDataElementOptions(index, mode);
|
||||
const vpixels = me._calculateBarValuePixels(index, options);
|
||||
const ipixels = me._calculateBarIndexPixels(index, ruler, options);
|
||||
for (let i = start; i < start + count; i++) {
|
||||
const options = sharedOptions || me.resolveDataElementOptions(i, mode);
|
||||
const vpixels = me._calculateBarValuePixels(i, options);
|
||||
const ipixels = me._calculateBarIndexPixels(i, ruler, options);
|
||||
|
||||
const properties = {
|
||||
horizontal,
|
||||
@ -265,7 +264,7 @@ export default class BarController extends DatasetController {
|
||||
if (includeOptions) {
|
||||
properties.options = options;
|
||||
}
|
||||
me.updateElement(rectangles[i], index, properties, mode);
|
||||
me.updateElement(rectangles[i], i, properties, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -65,10 +65,10 @@ export default class BubbleController extends DatasetController {
|
||||
const points = me._cachedMeta.data;
|
||||
|
||||
// Update Points
|
||||
me.updateElements(points, 0, mode);
|
||||
me.updateElements(points, 0, points.length, mode);
|
||||
}
|
||||
|
||||
updateElements(points, start, mode) {
|
||||
updateElements(points, start, count, mode) {
|
||||
const me = this;
|
||||
const reset = mode === 'reset';
|
||||
const {xScale, yScale} = me._cachedMeta;
|
||||
@ -76,10 +76,9 @@ export default class BubbleController extends DatasetController {
|
||||
const sharedOptions = me.getSharedOptions(firstOpts);
|
||||
const includeOptions = me.includeOptions(mode, sharedOptions);
|
||||
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
for (let i = start; i < start + count; i++) {
|
||||
const point = points[i];
|
||||
const index = start + i;
|
||||
const parsed = !reset && me.getParsed(index);
|
||||
const parsed = !reset && me.getParsed(i);
|
||||
const x = reset ? xScale.getPixelForDecimal(0.5) : xScale.getPixelForValue(parsed.x);
|
||||
const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(parsed.y);
|
||||
const properties = {
|
||||
@ -89,14 +88,14 @@ export default class BubbleController extends DatasetController {
|
||||
};
|
||||
|
||||
if (includeOptions) {
|
||||
properties.options = me.resolveDataElementOptions(index, mode);
|
||||
properties.options = me.resolveDataElementOptions(i, mode);
|
||||
|
||||
if (reset) {
|
||||
properties.options.radius = 0;
|
||||
}
|
||||
}
|
||||
|
||||
me.updateElement(point, index, properties, mode);
|
||||
me.updateElement(point, i, properties, mode);
|
||||
}
|
||||
|
||||
me.updateSharedOptions(sharedOptions, mode, firstOpts);
|
||||
|
||||
@ -104,7 +104,7 @@ export default class DoughnutController extends DatasetController {
|
||||
me.outerRadius = outerRadius - radiusLength * me._getRingWeightOffset(me.index);
|
||||
me.innerRadius = Math.max(me.outerRadius - radiusLength * chartWeight, 0);
|
||||
|
||||
me.updateElements(arcs, 0, mode);
|
||||
me.updateElements(arcs, 0, arcs.length, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,7 +117,7 @@ export default class DoughnutController extends DatasetController {
|
||||
return reset && opts.animation.animateRotate ? 0 : this.chart.getDataVisibility(i) ? me.calculateCircumference(meta._parsed[i] * opts.circumference / DOUBLE_PI) : 0;
|
||||
}
|
||||
|
||||
updateElements(arcs, start, mode) {
|
||||
updateElements(arcs, start, count, mode) {
|
||||
const me = this;
|
||||
const reset = mode === 'reset';
|
||||
const chart = me.chart;
|
||||
@ -139,9 +139,8 @@ export default class DoughnutController extends DatasetController {
|
||||
startAngle += me._circumference(i, reset);
|
||||
}
|
||||
|
||||
for (i = 0; i < arcs.length; ++i) {
|
||||
const index = start + i;
|
||||
const circumference = me._circumference(index, reset);
|
||||
for (i = start; i < start + count; ++i) {
|
||||
const circumference = me._circumference(i, reset);
|
||||
const arc = arcs[i];
|
||||
const properties = {
|
||||
x: centerX + me.offsetX,
|
||||
@ -153,11 +152,11 @@ export default class DoughnutController extends DatasetController {
|
||||
innerRadius
|
||||
};
|
||||
if (includeOptions) {
|
||||
properties.options = sharedOptions || me.resolveDataElementOptions(index, mode);
|
||||
properties.options = sharedOptions || me.resolveDataElementOptions(i, mode);
|
||||
}
|
||||
startAngle += circumference;
|
||||
|
||||
me.updateElement(arc, index, properties, mode);
|
||||
me.updateElement(arc, i, properties, mode);
|
||||
}
|
||||
me.updateSharedOptions(sharedOptions, mode, firstOpts);
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import DatasetController from '../core/core.datasetController';
|
||||
import {valueOrDefault} from '../helpers/helpers.core';
|
||||
import {isNumber} from '../helpers/helpers.math';
|
||||
import {resolve} from '../helpers/helpers.options';
|
||||
import {_lookupByKey} from '../helpers/helpers.collection';
|
||||
|
||||
export default class LineController extends DatasetController {
|
||||
|
||||
@ -13,8 +14,11 @@ export default class LineController extends DatasetController {
|
||||
update(mode) {
|
||||
const me = this;
|
||||
const meta = me._cachedMeta;
|
||||
const line = meta.dataset;
|
||||
const points = meta.data || [];
|
||||
const {dataset: line, data: points = []} = meta;
|
||||
const {start, count} = getStartAndCountOfVisiblePoints(meta, points);
|
||||
|
||||
me._drawStart = start;
|
||||
me._drawCount = count;
|
||||
|
||||
// Update Line
|
||||
// In resize mode only point locations change, so no need to set the points or options.
|
||||
@ -28,10 +32,10 @@ export default class LineController extends DatasetController {
|
||||
}
|
||||
|
||||
// Update Points
|
||||
me.updateElements(points, 0, mode);
|
||||
me.updateElements(points, start, count, mode);
|
||||
}
|
||||
|
||||
updateElements(points, start, mode) {
|
||||
updateElements(points, start, count, mode) {
|
||||
const me = this;
|
||||
const reset = mode === 'reset';
|
||||
const {xScale, yScale, _stacked} = me._cachedMeta;
|
||||
@ -40,14 +44,13 @@ export default class LineController extends DatasetController {
|
||||
const includeOptions = me.includeOptions(mode, sharedOptions);
|
||||
const spanGaps = valueOrDefault(me._config.spanGaps, me.chart.options.spanGaps);
|
||||
const maxGapLength = isNumber(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;
|
||||
let prevParsed;
|
||||
let prevParsed = start > 0 && me.getParsed(start - 1);
|
||||
|
||||
for (let i = 0; i < points.length; ++i) {
|
||||
const index = start + i;
|
||||
for (let i = start; i < start + count; ++i) {
|
||||
const point = points[i];
|
||||
const parsed = me.getParsed(index);
|
||||
const x = xScale.getPixelForValue(parsed.x, index);
|
||||
const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(_stacked ? me.applyStack(yScale, parsed) : parsed.y, index);
|
||||
const parsed = me.getParsed(i);
|
||||
const x = xScale.getPixelForValue(parsed.x, i);
|
||||
const y = reset ? yScale.getBasePixel() : yScale.getPixelForValue(_stacked ? me.applyStack(yScale, parsed) : parsed.y, i);
|
||||
const properties = {
|
||||
x,
|
||||
y,
|
||||
@ -56,10 +59,10 @@ export default class LineController extends DatasetController {
|
||||
};
|
||||
|
||||
if (includeOptions) {
|
||||
properties.options = sharedOptions || me.resolveDataElementOptions(index, mode);
|
||||
properties.options = sharedOptions || me.resolveDataElementOptions(i, mode);
|
||||
}
|
||||
|
||||
me.updateElement(point, index, properties, mode);
|
||||
me.updateElement(point, i, properties, mode);
|
||||
|
||||
prevParsed = parsed;
|
||||
}
|
||||
@ -167,3 +170,19 @@ LineController.defaults = {
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
function getStartAndCountOfVisiblePoints(meta, points) {
|
||||
const pointCount = points.length;
|
||||
|
||||
let start = 0;
|
||||
let count = pointCount;
|
||||
|
||||
if (meta._sorted) {
|
||||
const {iScale, _parsed} = meta;
|
||||
const {min, max, minDefined, maxDefined} = iScale.getUserBounds();
|
||||
start = minDefined ? Math.max(0, _lookupByKey(_parsed, iScale.axis, min).lo) : 0;
|
||||
count = (maxDefined ? Math.min(pointCount, _lookupByKey(_parsed, iScale.axis, max).hi + 1) : pointCount) - start;
|
||||
}
|
||||
|
||||
return {start, count};
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ export default class PolarAreaController extends DatasetController {
|
||||
const arcs = this._cachedMeta.data;
|
||||
|
||||
this._updateRadius();
|
||||
this.updateElements(arcs, 0, mode);
|
||||
this.updateElements(arcs, 0, arcs.length, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,7 +42,7 @@ export default class PolarAreaController extends DatasetController {
|
||||
me.innerRadius = me.outerRadius - radiusLength;
|
||||
}
|
||||
|
||||
updateElements(arcs, start, mode) {
|
||||
updateElements(arcs, start, count, mode) {
|
||||
const me = this;
|
||||
const reset = mode === 'reset';
|
||||
const chart = me.chart;
|
||||
@ -61,12 +61,11 @@ export default class PolarAreaController extends DatasetController {
|
||||
for (i = 0; i < start; ++i) {
|
||||
angle += me._computeAngle(i);
|
||||
}
|
||||
for (i = 0; i < arcs.length; i++) {
|
||||
for (i = start; i < start + count; i++) {
|
||||
const arc = arcs[i];
|
||||
const index = start + i;
|
||||
let startAngle = angle;
|
||||
let endAngle = angle + me._computeAngle(index);
|
||||
let outerRadius = this.chart.getDataVisibility(index) ? scale.getDistanceFromCenterForValue(dataset.data[index]) : 0;
|
||||
let endAngle = angle + me._computeAngle(i);
|
||||
let outerRadius = this.chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(dataset.data[i]) : 0;
|
||||
angle = endAngle;
|
||||
|
||||
if (reset) {
|
||||
@ -86,10 +85,10 @@ export default class PolarAreaController extends DatasetController {
|
||||
outerRadius,
|
||||
startAngle,
|
||||
endAngle,
|
||||
options: me.resolveDataElementOptions(index, mode)
|
||||
options: me.resolveDataElementOptions(i, mode)
|
||||
};
|
||||
|
||||
me.updateElement(arc, index, properties, mode);
|
||||
me.updateElement(arc, i, properties, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,21 +38,19 @@ export default class RadarController extends DatasetController {
|
||||
}
|
||||
|
||||
// Update Points
|
||||
me.updateElements(points, 0, mode);
|
||||
me.updateElements(points, 0, points.length, mode);
|
||||
}
|
||||
|
||||
updateElements(points, start, mode) {
|
||||
updateElements(points, start, count, mode) {
|
||||
const me = this;
|
||||
const dataset = me.getDataset();
|
||||
const scale = me._cachedMeta.rScale;
|
||||
const reset = mode === 'reset';
|
||||
let i;
|
||||
|
||||
for (i = 0; i < points.length; i++) {
|
||||
for (let i = start; i < start + count; i++) {
|
||||
const point = points[i];
|
||||
const index = start + i;
|
||||
const options = me.resolveDataElementOptions(index, mode);
|
||||
const pointPosition = scale.getPointPositionForValue(index, dataset.data[index]);
|
||||
const options = me.resolveDataElementOptions(i, mode);
|
||||
const pointPosition = scale.getPointPositionForValue(i, dataset.data[i]);
|
||||
|
||||
const x = reset ? scale.xCenter : pointPosition.x;
|
||||
const y = reset ? scale.yCenter : pointPosition.y;
|
||||
@ -65,7 +63,7 @@ export default class RadarController extends DatasetController {
|
||||
options
|
||||
};
|
||||
|
||||
me.updateElement(point, index, properties, mode);
|
||||
me.updateElement(point, i, properties, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -179,6 +179,8 @@ export default class DatasetController {
|
||||
this._data = undefined;
|
||||
this._objectData = undefined;
|
||||
this._sharedOptions = undefined;
|
||||
this._drawStart = undefined;
|
||||
this._drawCount = undefined;
|
||||
this.enableOptionSharing = false;
|
||||
|
||||
this.initialize();
|
||||
@ -380,11 +382,11 @@ export default class DatasetController {
|
||||
parsed = me.parsePrimitiveData(meta, data, start, count);
|
||||
}
|
||||
|
||||
|
||||
const isNotInOrderComparedToPrev = () => isNaN(cur[iAxis]) || (prev && cur[iAxis] < prev[iAxis]);
|
||||
for (i = 0; i < count; ++i) {
|
||||
meta._parsed[i + start] = cur = parsed[i];
|
||||
if (sorted) {
|
||||
if (prev && cur[iAxis] < prev[iAxis]) {
|
||||
if (isNotInOrderComparedToPrev()) {
|
||||
sorted = false;
|
||||
}
|
||||
prev = cur;
|
||||
@ -544,7 +546,7 @@ export default class DatasetController {
|
||||
parsed = _parsed[i];
|
||||
value = parsed[scale.axis];
|
||||
otherValue = parsed[otherScale.axis];
|
||||
return (isNaN(value) || otherMin > otherValue || otherMax < otherValue);
|
||||
return (isNaN(value) || isNaN(otherValue) || otherMin > otherValue || otherMax < otherValue);
|
||||
}
|
||||
|
||||
for (i = 0; i < ilen; ++i) {
|
||||
@ -633,13 +635,15 @@ export default class DatasetController {
|
||||
const elements = meta.data || [];
|
||||
const area = chart.chartArea;
|
||||
const active = [];
|
||||
let i, ilen;
|
||||
const start = me._drawStart || 0;
|
||||
const count = me._drawCount || (elements.length - start);
|
||||
let i;
|
||||
|
||||
if (meta.dataset) {
|
||||
meta.dataset.draw(ctx, area);
|
||||
meta.dataset.draw(ctx, area, start, count);
|
||||
}
|
||||
|
||||
for (i = 0, ilen = elements.length; i < ilen; ++i) {
|
||||
for (i = start; i < start + count; ++i) {
|
||||
const element = elements[i];
|
||||
if (element.active) {
|
||||
active.push(element);
|
||||
@ -648,7 +652,7 @@ export default class DatasetController {
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0, ilen = active.length; i < ilen; ++i) {
|
||||
for (i = 0; i < active.length; ++i) {
|
||||
active[i].draw(ctx, area);
|
||||
}
|
||||
}
|
||||
@ -936,10 +940,10 @@ export default class DatasetController {
|
||||
}
|
||||
me.parse(start, count);
|
||||
|
||||
me.updateElements(elements, start, 'reset');
|
||||
me.updateElements(data, start, count, 'reset');
|
||||
}
|
||||
|
||||
updateElements(element, start, mode) {} // eslint-disable-line no-unused-vars
|
||||
updateElements(element, start, count, mode) {} // eslint-disable-line no-unused-vars
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
||||
@ -33,6 +33,20 @@ function getLineMethod(options) {
|
||||
return lineTo;
|
||||
}
|
||||
|
||||
function pathVars(points, segment, params) {
|
||||
params = params || {};
|
||||
const count = points.length;
|
||||
const start = Math.max(params.start || 0, segment.start);
|
||||
const end = Math.min(params.end || count - 1, segment.end);
|
||||
|
||||
return {
|
||||
count,
|
||||
start,
|
||||
loop: segment.loop,
|
||||
ilen: end < start ? count + end - start : end - start
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create path from points, grouping by truncated x-coordinate
|
||||
* Points need to be in order by x-coordinate for this to work efficiently
|
||||
@ -43,17 +57,17 @@ function getLineMethod(options) {
|
||||
* @param {number} segment.end - end index of the segment, referring the points array
|
||||
* @param {boolean} segment.loop - indicates that the segment is a loop
|
||||
* @param {object} params
|
||||
* @param {object} params.move - move to starting point (vs line to it)
|
||||
* @param {object} params.reverse - path the segment from end to start
|
||||
* @param {boolean} params.move - move to starting point (vs line to it)
|
||||
* @param {boolean} params.reverse - path the segment from end to start
|
||||
* @param {number} params.start - limit segment to points starting from `start` index
|
||||
* @param {number} params.end - limit segment to points ending at `start` + `count` index
|
||||
*/
|
||||
function pathSegment(ctx, line, segment, params) {
|
||||
const {start, end, loop} = segment;
|
||||
const {points, options} = line;
|
||||
const {count, start, loop, ilen} = pathVars(points, segment, params);
|
||||
const lineMethod = getLineMethod(options);
|
||||
const count = points.length;
|
||||
// eslint-disable-next-line prefer-const
|
||||
let {move = true, reverse} = params || {};
|
||||
const ilen = end < start ? count + end - start : end - start;
|
||||
let i, point, prev;
|
||||
|
||||
for (i = 0; i <= ilen; ++i) {
|
||||
@ -90,15 +104,15 @@ function pathSegment(ctx, line, segment, params) {
|
||||
* @param {number} segment.end - end index of the segment, referring the points array
|
||||
* @param {boolean} segment.loop - indicates that the segment is a loop
|
||||
* @param {object} params
|
||||
* @param {object} params.move - move to starting point (vs line to it)
|
||||
* @param {object} params.reverse - path the segment from end to start
|
||||
* @param {boolean} params.move - move to starting point (vs line to it)
|
||||
* @param {boolean} params.reverse - path the segment from end to start
|
||||
* @param {number} params.start - limit segment to points starting from `start` index
|
||||
* @param {number} params.end - limit segment to points ending at `start` + `count` index
|
||||
*/
|
||||
function fastPathSegment(ctx, line, segment, params) {
|
||||
const points = line.points;
|
||||
const count = points.length;
|
||||
const {start, end} = segment;
|
||||
const {count, start, ilen} = pathVars(points, segment, params);
|
||||
const {move = true, reverse} = params || {};
|
||||
const ilen = end < start ? count + end - start : end - start;
|
||||
let avgX = 0;
|
||||
let countX = 0;
|
||||
let i, point, prevX, minY, maxY, lastY;
|
||||
@ -290,8 +304,10 @@ export default class Line extends Element {
|
||||
* @param {number} segment.end - end index of the segment, referring the points array
|
||||
* @param {boolean} segment.loop - indicates that the segment is a loop
|
||||
* @param {object} params
|
||||
* @param {object} params.move - move to starting point (vs line to it)
|
||||
* @param {object} params.reverse - path the segment from end to start
|
||||
* @param {boolean} params.move - move to starting point (vs line to it)
|
||||
* @param {boolean} params.reverse - path the segment from end to start
|
||||
* @param {number} params.start - limit segment to points starting from `start` index
|
||||
* @param {number} params.end - limit segment to points ending at `start` + `count` index
|
||||
* @returns {undefined|boolean} - true if the segment is a full loop (path should be closed)
|
||||
*/
|
||||
pathSegment(ctx, segment, params) {
|
||||
@ -302,16 +318,22 @@ export default class Line extends Element {
|
||||
/**
|
||||
* Append all segments of this line to current path.
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
* @param {number} [start]
|
||||
* @param {number} [count]
|
||||
* @returns {undefined|boolean} - true if line is a full loop (path should be closed)
|
||||
*/
|
||||
path(ctx) {
|
||||
path(ctx, start, count) {
|
||||
const me = this;
|
||||
const segments = me.segments;
|
||||
const ilen = segments.length;
|
||||
const segmentMethod = _getSegmentMethod(me);
|
||||
let loop = me._loop;
|
||||
|
||||
start = start || 0;
|
||||
count = count || (me.points.length - start);
|
||||
|
||||
for (let i = 0; i < ilen; ++i) {
|
||||
loop &= segmentMethod(ctx, me, segments[i]);
|
||||
loop &= segmentMethod(ctx, me, segments[i], {start, end: start + count - 1});
|
||||
}
|
||||
return !!loop;
|
||||
}
|
||||
@ -319,8 +341,11 @@ export default class Line extends Element {
|
||||
/**
|
||||
* Draw
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
* @param {object} chartArea
|
||||
* @param {number} [start]
|
||||
* @param {number} [count]
|
||||
*/
|
||||
draw(ctx) {
|
||||
draw(ctx, chartArea, start, count) {
|
||||
const options = this.options || {};
|
||||
const points = this.points || [];
|
||||
|
||||
@ -334,7 +359,7 @@ export default class Line extends Element {
|
||||
|
||||
ctx.beginPath();
|
||||
|
||||
if (this.path(ctx)) {
|
||||
if (this.path(ctx, start, count)) {
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 21 KiB |
BIN
test/fixtures/scale.time/ticks-reverse-linear.png
vendored
BIN
test/fixtures/scale.time/ticks-reverse-linear.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 21 KiB |
2
types/core/index.d.ts
vendored
2
types/core/index.d.ts
vendored
@ -338,7 +338,7 @@ export class DatasetController<E extends Element = Element, DSE extends Element
|
||||
linkScales(): void;
|
||||
getAllParsedValues(scale: Scale): number[];
|
||||
protected getLabelAndValue(index: number): { label: string; value: string };
|
||||
updateElements(elements: E[], start: number, mode: UpdateMode): void;
|
||||
updateElements(elements: E[], start: number, count: number, mode: UpdateMode): void;
|
||||
update(mode: UpdateMode): void;
|
||||
updateIndex(datasetIndex: number): void;
|
||||
protected getMaxOverflow(): boolean | number;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user