]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Support nested scriptable options for datasets (#9758)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Wed, 13 Oct 2021 12:41:22 +0000 (15:41 +0300)
committerGitHub <noreply@github.com>
Wed, 13 Oct 2021 12:41:22 +0000 (08:41 -0400)
* Support nested scriptable options for datasets

src/core/core.config.js
src/core/core.controller.js
test/specs/core.datasetController.tests.js

index 1523eb5c5c9b4f23bb39b6a7c07982e4e21c7c4c..ef129b88f4df2ac3cee1ba9f4e8340d0b2da4a54 100644 (file)
@@ -371,12 +371,18 @@ function getResolver(resolverCache, scopes, prefixes) {
   return cached;
 }
 
+const hasFunction = value => isObject(value)
+  && Object.keys(value).reduce((acc, key) => acc || isFunction(value[key]), false);
+
 function needContext(proxy, names) {
   const {isScriptable, isIndexable} = _descriptors(proxy);
 
   for (const prop of names) {
-    if ((isScriptable(prop) && isFunction(proxy[prop]))
-      || (isIndexable(prop) && isArray(proxy[prop]))) {
+    const scriptable = isScriptable(prop);
+    const indexable = isIndexable(prop);
+    const value = (indexable || scriptable) && proxy[prop];
+    if ((scriptable && (isFunction(value) || hasFunction(value)))
+      || (indexable && isArray(value))) {
       return true;
     }
   }
index 19cfeca0cc277dabd82fc17fbe35ca52006f0159..3ba3b2fd748478ae61f7a1b4f523b01f0d7f90ff 100644 (file)
@@ -7,7 +7,7 @@ import PluginService from './core.plugins';
 import registry from './core.registry';
 import Config, {determineAxis, getIndexAxis} from './core.config';
 import {retinaScale, _isDomSupported} from '../helpers/helpers.dom';
-import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef, setsEqual, defined} from '../helpers/helpers.core';
+import {each, callback as callCallback, uid, valueOrDefault, _elementsEqual, isNullOrUndef, setsEqual, defined, isFunction} from '../helpers/helpers.core';
 import {clearCanvas, clipArea, unclipArea, _isPointInArea} from '../helpers/helpers.canvas';
 // @ts-ignore
 import {version} from '../../package.json';
@@ -536,14 +536,12 @@ class Chart {
         * @private
         */
   _updateDatasets(mode) {
-    const isFunction = typeof mode === 'function';
-
     if (this.notifyPlugins('beforeDatasetsUpdate', {mode, cancelable: true}) === false) {
       return;
     }
 
     for (let i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
-      this._updateDataset(i, isFunction ? mode({datasetIndex: i}) : mode);
+      this._updateDataset(i, isFunction(mode) ? mode({datasetIndex: i}) : mode);
     }
 
     this.notifyPlugins('afterDatasetsUpdate', {mode});
index 3f08d209e26a79aed32791e117261debb65f1969..3ec7a661260cca46975b14c4f87e9969b8556a8b 100644 (file)
@@ -897,6 +897,28 @@ describe('Chart.DatasetController', function() {
       expect(opts0.$shared).not.toBeTrue();
       expect(Object.isFrozen(opts0)).toBeFalse();
     });
+
+    it('should support nested scriptable options', function() {
+      const chart = acquireChart({
+        type: 'line',
+        data: {
+          datasets: [{
+            data: [100, 120, 130],
+            fill: {
+              value: (ctx) => ctx.type === 'dataset' ? 75 : 0
+            }
+          }]
+        },
+      });
+
+      const controller = chart.getDatasetMeta(0).controller;
+      const opts = controller.resolveDatasetElementOptions();
+      expect(opts).toEqualOptions({
+        fill: {
+          value: 75
+        }
+      });
+    });
   });
 
   describe('_resolveAnimations', function() {