Skip to content

Commit a0d0334

Browse files
committed
Improvement - Internal lib - Add keepNull option on sanitizeArray util
1 parent d2b6817 commit a0d0334

File tree

2 files changed

+101
-7
lines changed

2 files changed

+101
-7
lines changed

src/lib.js

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2075,9 +2075,10 @@ export function hasDeepProperty(obj, path) {
20752075
});
20762076
}
20772077

2078-
export function sanitizeArray(arr, keys = []) {
2078+
export function sanitizeArray(arr, keys = [], keepNull = false) {
20792079

20802080
function sanitizeValue(value) {
2081+
if (keepNull && (value === null)) return null;
20812082
if (typeof value === 'string' && isNaN(Number(value))) return value;
20822083
return (typeof value === 'number' && isFinite(value)) ? value : 0;
20832084
}
@@ -2133,6 +2134,7 @@ export function sanitizeArray(arr, keys = []) {
21332134
return sanitize(arr);
21342135
}
21352136

2137+
21362138
export function setOpacity(hex, opac = 100) {
21372139
if (hex.length === 9) {
21382140
return hex.substring(0, 7) + opacity[opac]
@@ -3304,6 +3306,92 @@ export function triggerResize(el, { delta = 1, delay = 20, disableTransitions =
33043306
}, delay);
33053307
}
33063308

3309+
export function cacheLastResult(fn) {
3310+
let prevKey = null;
3311+
let prevVal = null;
3312+
return (...args) => {
3313+
const key = JSON.stringify(args);
3314+
if (key === prevKey) return prevVal;
3315+
prevKey = key;
3316+
prevVal = fn(...args);
3317+
return prevVal;
3318+
};
3319+
}
3320+
3321+
// VueUiXy, VueUiStackbar
3322+
export const buildDisplayedTimeLabels = cacheLastResult((
3323+
showOnlyFirstAndLast,
3324+
showOnlyAtModulo,
3325+
moduloBase,
3326+
visTexts,
3327+
allTexts,
3328+
startAbs,
3329+
selIdx,
3330+
maxSeriesCount
3331+
) => {
3332+
if (showOnlyFirstAndLast) {
3333+
if (visTexts.length <= 2) {
3334+
return visTexts.map((t, i) => ({ text: t, absoluteIndex: i }));
3335+
}
3336+
const out = visTexts.map((t, i) => {
3337+
const keep = (i === 0) || (i === visTexts.length - 1) || (selIdx != null && i === selIdx);
3338+
return { text: keep ? t : '', absoluteIndex: i };
3339+
});
3340+
return out;
3341+
}
3342+
3343+
if (!showOnlyAtModulo) {
3344+
return visTexts.map((t, i) => ({ text: t, absoluteIndex: i }));
3345+
}
3346+
3347+
const mod = Math.max(1, moduloBase || 1);
3348+
if (maxSeriesCount <= mod) {
3349+
return visTexts.map((t, i) => ({ text: t, absoluteIndex: i }));
3350+
}
3351+
3352+
const candidates = [];
3353+
for (let i = 0; i < visTexts.length; i += 1) {
3354+
const cur = visTexts[i] ?? '';
3355+
if (!cur) continue;
3356+
const prevAbs = startAbs + i - 1 >= 0 ? (allTexts[startAbs + i - 1] ?? '') : null;
3357+
if (cur !== prevAbs) candidates.push(i);
3358+
}
3359+
3360+
if (!candidates.length) {
3361+
return visTexts.map((_t, i) => ({ text: '', absoluteIndex: i }));
3362+
}
3363+
3364+
const C = candidates.length;
3365+
const base = mod;
3366+
const minK = Math.max(2, Math.min(base - 3, C));
3367+
const maxK = Math.min(C, base + 3);
3368+
3369+
let bestK = Math.min(base, C);
3370+
let bestScore = Infinity;
3371+
3372+
for (let k = minK; k <= maxK; k += 1) {
3373+
const remainder = (C - 1) % (k - 1);
3374+
const drift = Math.abs(k - base);
3375+
const score = remainder * 10 + drift;
3376+
if (score < bestScore) { bestScore = score; bestK = k; }
3377+
}
3378+
3379+
const picked = new Set();
3380+
if (bestK <= 1) {
3381+
picked.add(candidates[Math.round((C - 1) / 2)]);
3382+
} else {
3383+
const step = (C - 1) / (bestK - 1);
3384+
for (let j = 0; j < bestK; j += 1) {
3385+
picked.add(candidates[Math.round(j * step)]);
3386+
}
3387+
}
3388+
3389+
return visTexts.map((t, i) => ({
3390+
text: picked.has(i) ? t : '',
3391+
absoluteIndex: i
3392+
}));
3393+
});
3394+
33073395
const lib = {
33083396
XMLNS,
33093397
abbreviate,
@@ -3312,7 +3400,9 @@ const lib = {
33123400
applyDataLabel,
33133401
assignStackRatios,
33143402
autoFontSize,
3403+
buildDisplayedTimeLabels,
33153404
buildInterLineAreas,
3405+
cacheLastResult,
33163406
calcLinearProgression,
33173407
calcMarkerOffsetX,
33183408
calcMarkerOffsetY,

tests/lib.test.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2030,25 +2030,29 @@ describe("hasDeepProperty", () => {
20302030
});
20312031

20322032
describe("sanitizeArray", () => {
2033-
const source0 = [1, 2, 3, NaN, undefined, Infinity, -Infinity];
2033+
const source0 = [1, 2, 3, NaN, undefined, Infinity, -Infinity, null];
20342034
test("sanitizes an array of numbers", () => {
2035-
expect(sanitizeArray(source0)).toStrictEqual([1, 2, 3, 0, 0, 0, 0]);
2035+
expect(sanitizeArray(source0)).toStrictEqual([1, 2, 3, 0, 0, 0, 0, 0]);
20362036
});
20372037

20382038
const source1 = [
20392039
{
2040-
values: [1, NaN, undefined, Infinity, -Infinity],
2041-
value: [2, NaN, undefined, Infinity, -Infinity],
2040+
values: [1, NaN, undefined, Infinity, -Infinity, null],
2041+
value: [2, NaN, undefined, Infinity, -Infinity, null],
20422042
},
20432043
];
20442044
test("sanitizes an array of objects where some attributes are arrays of numbers", () => {
20452045
expect(sanitizeArray(source1, ["values, value"])).toStrictEqual([
20462046
{
2047-
value: [2, 0, 0, 0, 0],
2048-
values: [1, 0, 0, 0, 0],
2047+
value: [2, 0, 0, 0, 0, 0],
2048+
values: [1, 0, 0, 0, 0, 0],
20492049
},
20502050
]);
20512051
});
2052+
const withNull = [null, 1, null, 2, NaN, undefined, Infinity, -Infinity];
2053+
test('keeps null values', () => {
2054+
expect(sanitizeArray(withNull, [], true)).toStrictEqual([null, 1, null, 2, 0, 0, 0, 0])
2055+
})
20522056
});
20532057

20542058
describe("lightenHexColor", () => {

0 commit comments

Comments
 (0)