]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Do not use offsetX/Y in shadow DOM (#8082)
authorJukka Kurkela <jukka.kurkela@gmail.com>
Fri, 20 Nov 2020 20:59:48 +0000 (22:59 +0200)
committerGitHub <noreply@github.com>
Fri, 20 Nov 2020 20:59:48 +0000 (15:59 -0500)
Do not use offsetX/Y in shadow DOM

src/helpers/helpers.dom.js
test/specs/helpers.dom.tests.js
test/utils.js

index 12eb7f3a622897dbc6abc8bc9c8ee8b0026e09ff..50c2654d997c3310a104a44108d1ed3c8bdf8892 100644 (file)
@@ -52,6 +52,8 @@ function getPositionedStyle(styles, style, suffix) {
        return result;
 }
 
+const useOffsetPos = (x, y, target) => (x > 0 || y > 0) && (!target || !target.shadowRoot);
+
 function getCanvasPosition(evt, canvas) {
        const e = evt.originalEvent || evt;
        const touches = e.touches;
@@ -59,7 +61,7 @@ function getCanvasPosition(evt, canvas) {
        const {offsetX, offsetY} = source;
        let box = false;
        let x, y;
-       if (offsetX > 0 || offsetY > 0) {
+       if (useOffsetPos(offsetX, offsetY, e.target)) {
                x = offsetX;
                y = offsetY;
        } else {
index 11f13dec2d7257d5e20343743aa370bf346afd86..9cd370d055895857d7749a35d5a4cda5c02d064c 100644 (file)
@@ -345,5 +345,59 @@ describe('DOM helpers tests', function() {
                        expect(Math.abs(pos3.x - Math.round((event.clientX - rect3.x - 10) / 360 * 400))).toBeLessThanOrEqual(1);
                        expect(Math.abs(pos3.y - Math.round((event.clientY - rect3.y - 10) / 360 * 400))).toBeLessThanOrEqual(1);
                });
+
+               it ('should get the correct relative position for a node in a ShadowRoot', function() {
+                       const event = {
+                               offsetX: 50,
+                               offsetY: 100,
+                               clientX: 50,
+                               clientY: 100
+                       };
+
+                       const chart = window.acquireChart({}, {
+                               canvas: {
+                                       height: 200,
+                                       width: 200,
+                               },
+                               useShadowDOM: true
+                       });
+
+                       event.target = chart.canvas.parentNode.host;
+                       expect(event.target.shadowRoot).not.toEqual(null);
+                       const rect = chart.canvas.getBoundingClientRect();
+                       const pos = helpers.getRelativePosition(event, chart);
+                       expect(Math.abs(pos.x - Math.round(event.clientX - rect.x))).toBeLessThanOrEqual(1);
+                       expect(Math.abs(pos.y - Math.round(event.clientY - rect.y))).toBeLessThanOrEqual(1);
+
+                       const chart2 = window.acquireChart({}, {
+                               canvas: {
+                                       height: 200,
+                                       width: 200,
+                                       style: 'padding: 10px'
+                               },
+                               useShadowDOM: true
+                       });
+
+                       event.target = chart2.canvas.parentNode.host;
+                       const rect2 = chart2.canvas.getBoundingClientRect();
+                       const pos2 = helpers.getRelativePosition(event, chart2);
+                       expect(Math.abs(pos2.x - Math.round((event.clientX - rect2.x - 10) / 180 * 200))).toBeLessThanOrEqual(1);
+                       expect(Math.abs(pos2.y - Math.round((event.clientY - rect2.y - 10) / 180 * 200))).toBeLessThanOrEqual(1);
+
+                       const chart3 = window.acquireChart({}, {
+                               canvas: {
+                                       height: 200,
+                                       width: 200,
+                                       style: 'width: 400px, height: 400px; padding: 10px'
+                               },
+                               useShadowDOM: true
+                       });
+
+                       event.target = chart3.canvas.parentNode.host;
+                       const rect3 = chart3.canvas.getBoundingClientRect();
+                       const pos3 = helpers.getRelativePosition(event, chart3);
+                       expect(Math.abs(pos3.x - Math.round((event.clientX - rect3.x - 10) / 360 * 400))).toBeLessThanOrEqual(1);
+                       expect(Math.abs(pos3.y - Math.round((event.clientY - rect3.y - 10) / 360 * 400))).toBeLessThanOrEqual(1);
+               });
        });
 });
index 010971dde55d5a6d6f728f1d28ef839a2a3ab8bd..ee443880ef7275d579bfeaeecab04dbd9225c311 100644 (file)
@@ -30,6 +30,7 @@ function readImageData(url, callback) {
  * @param {object} options.canvas - Canvas attributes.
  * @param {object} options.wrapper - Canvas wrapper attributes.
  * @param {boolean} options.useOffscreenCanvas - use an OffscreenCanvas instead of the normal HTMLCanvasElement.
+ * @param {boolean} options.useShadowDOM - use shadowDom
  * @param {boolean} options.persistent - If true, the chart will not be released after the spec.
  */
 function acquireChart(config, options) {
@@ -60,7 +61,15 @@ function acquireChart(config, options) {
        config.options.responsive = config.options.responsive === undefined ? false : config.options.responsive;
        config.options.locale = config.options.locale || 'en-US';
 
-       wrapper.appendChild(canvas);
+       if (options.useShadowDOM) {
+               if (!wrapper.attachShadow) {
+                       // If shadowDOM is not supported by the browsers, mark test as 'pending'.
+                       return pending();
+               }
+               wrapper.attachShadow({mode: 'open'}).appendChild(canvas);
+       } else {
+               wrapper.appendChild(canvas);
+       }
        window.document.body.appendChild(wrapper);
 
        try {
@@ -71,8 +80,7 @@ function acquireChart(config, options) {
                                // test.
                                // TODO: switch to skip() once it's implemented (https://github.com/jasmine/jasmine/issues/1709), or
                                // remove if all browsers implement `transferControlToOffscreen`
-                               pending();
-                               return;
+                               return pending();
                        }
                        var offscreenCanvas = canvas.transferControlToOffscreen();
                        ctx = offscreenCanvas.getContext('2d');