Skip to content

Commit 34a669e

Browse files
committed
Move diff function to helpers and update to handle nested arrays
1 parent b480d04 commit 34a669e

File tree

2 files changed

+34
-42
lines changed

2 files changed

+34
-42
lines changed

src/plot_api/helpers.js

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ function getParent(attr) {
455455
if (tail > 0) return attr.substr(0, tail);
456456
}
457457

458-
/*
458+
/**
459459
* hasParent: does an attribute object contain a parent of the given attribute?
460460
* for example, given 'images[2].x' do we also have 'images' or 'images[2]'?
461461
*
@@ -475,6 +475,7 @@ exports.hasParent = function (aobj, attr) {
475475
return false;
476476
};
477477

478+
const AX_LETTERS = ['x', 'y', 'z'];
478479
/**
479480
* Empty out types for all axes containing these traces so we auto-set them again
480481
*
@@ -483,12 +484,11 @@ exports.hasParent = function (aobj, attr) {
483484
* @param {object} layoutUpdate: any update being done concurrently to the layout,
484485
* which may supercede clearing the axis types
485486
*/
486-
var axLetters = ['x', 'y', 'z'];
487487
exports.clearAxisTypes = function (gd, traces, layoutUpdate) {
488488
for (var i = 0; i < traces.length; i++) {
489489
var trace = gd._fullData[i];
490490
for (var j = 0; j < 3; j++) {
491-
var ax = getFromTrace(gd, trace, axLetters[j]);
491+
var ax = getFromTrace(gd, trace, AX_LETTERS[j]);
492492

493493
// do not clear log type - that's never an auto result so must have been intentional
494494
if (ax && ax.type !== 'log') {
@@ -507,3 +507,32 @@ exports.clearAxisTypes = function (gd, traces, layoutUpdate) {
507507
}
508508
}
509509
};
510+
511+
/**
512+
* Check if a collection (object or array) has changed given two versions of
513+
* the collection: old and new.
514+
*
515+
* @param {Object|Array} oldCollection: Old version of collection to compare
516+
* @param {Object|Array} newCollection: New version of collection to compare
517+
*/
518+
const hasCollectionChanged = (oldCollection, newCollection) => {
519+
const isArrayOrObject = (...vals) => vals.every((v) => Lib.isPlainObject(v)) || vals.every((v) => Array.isArray(v));
520+
if ([oldCollection, newCollection].every((a) => Array.isArray(a))) {
521+
if (oldCollection.length !== newCollection.length) return true;
522+
523+
return oldCollection.some((oldVal, i) => {
524+
const newVal = newCollection[i];
525+
if (oldVal !== newVal) return isArrayOrObject(oldVal, newVal) ? hasCollectionChanged(oldVal, newVal) : true;
526+
});
527+
} else {
528+
if (Object.keys(oldCollection).length !== Object.keys(newCollection).length) return true;
529+
530+
return Object.keys(oldCollection).some((k) => {
531+
if (k.startsWith('_')) return false;
532+
const oldVal = oldCollection[k];
533+
const newVal = newCollection[k];
534+
if (oldVal !== newVal) return isArrayOrObject(oldVal, newVal) ? hasCollectionChanged(oldVal, newVal) : true;
535+
});
536+
}
537+
};
538+
exports.hasCollectionChanged = hasCollectionChanged;

src/plot_api/plot_api.js

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2607,10 +2607,10 @@ function react(gd, data, layout, config) {
26072607
// assume that if there's a config at all, we're reacting to it too,
26082608
// and completely replace the previous config
26092609
if (config) {
2610-
var oldConfig = Lib.extendDeep({}, gd._context);
2610+
const oldConfig = Lib.extendDeep({}, gd._context);
26112611
gd._context = undefined;
26122612
setPlotContext(gd, config);
2613-
configChanged = diffConfig(oldConfig, gd._context);
2613+
configChanged = helpers.hasCollectionChanged(oldConfig, gd._context);
26142614
}
26152615

26162616
if (configChanged) {
@@ -3028,43 +3028,6 @@ function getDiffFlags(oldContainer, newContainer, outerparts, opts) {
30283028
}
30293029
}
30303030

3031-
/*
3032-
* simple diff for config - for now, just treat all changes as equivalent
3033-
*/
3034-
function diffConfig(oldConfig, newConfig) {
3035-
var key;
3036-
3037-
for (key in oldConfig) {
3038-
if (key.charAt(0) === '_') continue;
3039-
var oldVal = oldConfig[key];
3040-
var newVal = newConfig[key];
3041-
if (oldVal !== newVal) {
3042-
if (Lib.isPlainObject(oldVal) && Lib.isPlainObject(newVal)) {
3043-
if (diffConfig(oldVal, newVal)) {
3044-
return true;
3045-
}
3046-
} else if (Array.isArray(oldVal) && Array.isArray(newVal)) {
3047-
if (oldVal.length !== newVal.length) {
3048-
return true;
3049-
}
3050-
for (var i = 0; i < oldVal.length; i++) {
3051-
if (oldVal[i] !== newVal[i]) {
3052-
if (Lib.isPlainObject(oldVal[i]) && Lib.isPlainObject(newVal[i])) {
3053-
if (diffConfig(oldVal[i], newVal[i])) {
3054-
return true;
3055-
}
3056-
} else {
3057-
return true;
3058-
}
3059-
}
3060-
}
3061-
} else {
3062-
return true;
3063-
}
3064-
}
3065-
}
3066-
}
3067-
30683031
/**
30693032
* Animate to a frame, sequence of frame, frame group, or frame definition
30703033
*

0 commit comments

Comments
 (0)