Commit 0fd302bd authored by Robert Knight's avatar Robert Knight

Remove `Element.closest` polyfill

Element.closest is natively supported [1] by our minimum browser targets.

[1] https://developer.mozilla.org/en-US/docs/Web/API/Element/closest#Browser_compatibility
parent 2e6b8a6e
......@@ -15,7 +15,6 @@ import {
} from './highlighter';
import * as rangeUtil from './range-util';
import selections from './selections';
import { closest } from '../shared/dom-element';
import { normalizeURI } from './util/url';
/**
......@@ -666,8 +665,7 @@ export default class Guest extends Delegator {
*/
isEventInAnnotator(event) {
return (
closest(/** @type {Element} */ (event.target), '.annotator-frame') !==
null
/** @type {Element} */ (event.target).closest('.annotator-frame') !== null
);
}
......
import { closest } from '../shared/dom-element';
const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
function isCSSPropertySupported(property, value) {
......@@ -35,7 +33,7 @@ function getPdfCanvas(highlightEl) {
// It also assumes that the `highlightEl` element is somewhere under
// the `.textLayer` div.
const pageEl = closest(highlightEl, '.page');
const pageEl = highlightEl.closest('.page');
if (!pageEl) {
return null;
}
......@@ -170,8 +168,7 @@ export function highlightRange(normedRange, cssClass = 'hypothesis-highlight') {
// a PDF. These highlights should be invisible.
const isPlaceholder =
textNodes.length > 0 &&
closest(
/** @type {Element} */ (textNodes[0].parentNode),
/** @type {Element} */ (textNodes[0].parentNode).closest(
'.annotator-placeholder'
) !== null;
......
/**
* Ponyfills [1] for DOM element methods that are not supported in all browsers.
*
* [1] https://github.com/sindresorhus/ponyfill
*/
/**
* Implementation of `element.closest(selector)`. This is used to support browsers
* (IE 11) that don't have a native implementation.
*
* @param {Element|null} element
* @param {string} selector
*/
export function closest(element, selector) {
while (element) {
if (element.matches(selector)) {
return element;
}
element = element.parentElement;
}
return null;
}
import { closest } from '../dom-element';
describe('shared/dom-element', () => {
let container;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
container.remove();
});
describe('closest', () => {
it('returns closest matching ancestor', () => {
container.innerHTML = `
<div class="outer">
<div class="middle">
<div class="inner"></div>
</div>
</div>
`;
const el = container.querySelector('.inner');
const target = container.querySelector('.outer');
assert.equal(closest(el, '.inner'), el);
assert.equal(closest(el, '.outer'), target);
assert.isNull(closest(el, '.no-match'));
});
});
});
......@@ -4,7 +4,6 @@ import { createElement } from 'preact';
import { useCallback, useMemo } from 'preact/hooks';
import propTypes from 'prop-types';
import { closest } from '../../shared/dom-element';
import useStore from '../store/use-store';
import { withServices } from '../util/service-context';
......@@ -50,9 +49,11 @@ function ThreadCard({ frameSync, settings, thread }) {
/**
* Is the target's event an <a> or <button> element, or does it have
* either as an ancestor?
*
* @param {Element} target
*/
const isFromButtonOrLink = target => {
return !!closest(target, 'button') || !!closest(target, 'a');
return !!target.closest('button') || !!target.closest('a');
};
return (
......@@ -61,7 +62,7 @@ function ThreadCard({ frameSync, settings, thread }) {
onClick={e => {
// Prevent click events intended for another action from
// triggering a page scroll.
if (!isFromButtonOrLink(e.target)) {
if (!isFromButtonOrLink(/** @type {Element} */ (e.target))) {
scrollToAnnotation(threadTag);
}
}}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment