Skip to content

Commit

Permalink
fix(dom): handle slotted parent transform position (#8158)
Browse files Browse the repository at this point in the history
* fix(dom): handle slotted parent transform position

* fix(test): add test to cover getPointerPosition

* run all tests

---------

Co-authored-by: mister-ben <git@misterben.me>
  • Loading branch information
weiz18 and mister-ben authored May 3, 2024
1 parent 8050466 commit 9946a19
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/js/utils/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
16 changes: 16 additions & 0 deletions test/unit/utils/custom-element.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
84 changes: 84 additions & 0 deletions test/unit/utils/dom.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -687,6 +688,89 @@ QUnit.test('isSingleLeftClick() checks return values for mousedown event', funct
assert.ok(Dom.isSingleLeftClick(mouseEvent), 'a tap-to-click on Mac trackpad 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 = `
<test-slot-element id="slides" style="position: absolute" data-style="position: relative; transform: translate(5px);">
<div class="video-01">
<div class="progress-01" style="${progressStyle}"></div>
</div>
<div class="video-02">
<div class="progress-02" style="${progressStyle}"></div>
</div>
</test-slot-element>
`;
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
Expand Down

0 comments on commit 9946a19

Please # to comment.