diff --git a/src/js/utils/dom.js b/src/js/utils/dom.js index b6c2caea20..4201153baa 100644 --- a/src/js/utils/dom.js +++ b/src/js/utils/dom.js @@ -580,7 +580,15 @@ export function getPointerPosition(el, event) { translated.y += values[13]; } - item = item.parentNode; + if (item.assignedSlot && item.assignedSlot.parentElement && window.WebKitCSSMatrix) { + const transformValue = window.getComputedStyle(item.assignedSlot.parentElement).transform; + const matrix = new window.WebKitCSSMatrix(transformValue); + + translated.x += matrix.m41; + translated.y += matrix.m42; + } + + item = item.parentNode || item.host; } } diff --git a/test/unit/utils/custom-element.test.js b/test/unit/utils/custom-element.test.js index 6322e83c40..163a38dfc0 100644 --- a/test/unit/utils/custom-element.test.js +++ b/test/unit/utils/custom-element.test.js @@ -23,7 +23,23 @@ export class TestCustomElement extends HTMLElement { } } +export class TestSlotElement extends HTMLElement { + + constructor() { + super(); + const shadowRoot = this.attachShadow({ mode: 'open' }); + const wrapperEl = document.createElement('div'); + + wrapperEl.style = this.dataset.style; + const slot = document.createElement('slot'); + + wrapperEl.appendChild(slot); + shadowRoot.appendChild(wrapperEl); + } +} + // Not supported on Chrome < 54 if ('customElements' in window) { window.customElements.define('test-custom-element', TestCustomElement); + window.customElements.define('test-slot-element', TestSlotElement); } diff --git a/test/unit/utils/dom.test.js b/test/unit/utils/dom.test.js index 8a01d7068c..d5c97cf3de 100644 --- a/test/unit/utils/dom.test.js +++ b/test/unit/utils/dom.test.js @@ -3,6 +3,7 @@ import document from 'global/document'; import sinon from 'sinon'; import * as Dom from '../../../src/js/utils/dom.js'; import TestHelpers from '../test-helpers.js'; +import * as browser from '../../../src/js/utils/browser.js'; QUnit.module('utils/dom'); @@ -687,6 +688,89 @@ QUnit.test('isSingleLeftClick() checks return values for mousedown event', funct assert.ok(Dom.isSingleLeftClick(mouseEvent), 'a touch event on simulated mobiles is a single left click'); }); +QUnit.test('dom.getPointerPosition should return position with translated', function(assert) { + const wrapper = document.createElement('div'); + + const width = '100px'; + const height = '50px'; + + wrapper.style.width = width; + wrapper.style.height = height; + wrapper.style.position = 'absolute'; + wrapper.style.top = '0'; + wrapper.style.left = '0'; + + let position; + + document.body.appendChild(wrapper); + const event = { + offsetX: 20, + offsetY: 0, + target: wrapper + }; + + position = Dom.getPointerPosition(wrapper, event); + + // Default click on element without any transform + assert.deepEqual(position, { x: 0.2, y: 1 }); + + const origIOS = browser.IS_IOS; + + wrapper.style.transform = 'translate(5px)'; + + const transformedTouch = { + offsetX: 20, + offsetY: 0, + target: wrapper, + changedTouches: [ + { + pageX: 20, + pageY: 0 + } + ] + }; + + // Ignore translate x/y when not in IOS + position = Dom.getPointerPosition(wrapper, transformedTouch); + assert.deepEqual(position, { x: 0.2, y: 1 }); + + // Add calculate with IOS to true + browser.stub_IS_IOS(true); + position = Dom.getPointerPosition(wrapper, transformedTouch); + assert.deepEqual(position, { x: 0.15, y: 1 }); + + // Create complex template where position of each video is controlled by + // a web component with transform + wrapper.style.transform = ''; + const progressStyle = `position: absolute; height: ${height}; width: ${width};`; + + wrapper.innerHTML = ` + +
+
+
+
+
+
+
+ `; + document.body.appendChild(wrapper); + + const slottedProgressBar = wrapper.querySelector('div.progress-02'); + + // Handle slot elements pointer position + transformedTouch.target = slottedProgressBar; + position = Dom.getPointerPosition(slottedProgressBar, transformedTouch); + assert.deepEqual(position, { x: 0.15, y: 1 }); + + // Non IOS slot element pointer position + browser.stub_IS_IOS(false); + position = Dom.getPointerPosition(slottedProgressBar, transformedTouch); + assert.deepEqual(position, { x: 0.20, y: 1 }); + + browser.stub_IS_IOS(origIOS); +}); + QUnit.test('Dom.copyStyleSheetsToWindow() copies all style sheets to a window', function(assert) { /** * This test is checking that styles are copied by comparing strings in original stylesheets to those in