fix: inline pointer events now correctly work in Chrome (#11695)

* fix: inline pointer events now correctly work in Chrome

* fix more
pull/11663/head
Dominic Gannaway 7 months ago committed by GitHub
parent e6f8e95199
commit a5fd28a14b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: inline pointer events now correctly work in Chrome

@ -2,7 +2,7 @@ import { DEV } from 'esm-env';
import { hydrating } from '../hydration.js'; import { hydrating } from '../hydration.js';
import { get_descriptors, get_prototype_of, map_get, map_set } from '../../utils.js'; import { get_descriptors, get_prototype_of, map_get, map_set } from '../../utils.js';
import { AttributeAliases, DelegatedEvents, namespace_svg } from '../../../../constants.js'; import { AttributeAliases, DelegatedEvents, namespace_svg } from '../../../../constants.js';
import { delegate } from './events.js'; import { create_event, delegate } from './events.js';
import { autofocus } from './misc.js'; import { autofocus } from './misc.js';
import { effect, effect_root } from '../../reactivity/effects.js'; import { effect, effect_root } from '../../reactivity/effects.js';
import * as w from '../../warnings.js'; import * as w from '../../warnings.js';
@ -151,9 +151,13 @@ export function set_attributes(element, prev, next, lowercase_attributes, css_ha
if (!delegated) { if (!delegated) {
// we use `addEventListener` here because these events are not delegated // we use `addEventListener` here because these events are not delegated
if (!prev) { if (!prev) {
events.push([key, value, () => element.addEventListener(event_name, value, opts)]); events.push([
key,
value,
() => (next[key] = create_event(event_name, element, value, opts))
]);
} else { } else {
element.addEventListener(event_name, value, opts); next[key] = create_event(event_name, element, value, opts);
} }
} else { } else {
// @ts-ignore // @ts-ignore

@ -2,6 +2,7 @@ import { render_effect } from '../../reactivity/effects.js';
import { all_registered_events, root_event_handles } from '../../render.js'; import { all_registered_events, root_event_handles } from '../../render.js';
import { define_property, is_array } from '../../utils.js'; import { define_property, is_array } from '../../utils.js';
import { hydrating } from '../hydration.js'; import { hydrating } from '../hydration.js';
import { queue_task } from '../task.js';
/** /**
* SSR adds onload and onerror attributes to catch those events before the hydration. * SSR adds onload and onerror attributes to catch those events before the hydration.
@ -34,18 +35,14 @@ export function replay_events(dom) {
* @param {string} event_name * @param {string} event_name
* @param {Element} dom * @param {Element} dom
* @param {EventListener} handler * @param {EventListener} handler
* @param {boolean} capture * @param {AddEventListenerOptions} options
* @param {boolean} [passive]
* @returns {void}
*/ */
export function event(event_name, dom, handler, capture, passive) { export function create_event(event_name, dom, handler, options) {
var options = { capture, passive };
/** /**
* @this {EventTarget} * @this {EventTarget}
*/ */
function target_handler(/** @type {Event} */ event) { function target_handler(/** @type {Event} */ event) {
if (!capture) { if (!options.capture) {
// Only call in the bubble phase, else delegated events would be called before the capturing events // Only call in the bubble phase, else delegated events would be called before the capturing events
handle_event_propagation(dom, event); handle_event_propagation(dom, event);
} }
@ -54,7 +51,32 @@ export function event(event_name, dom, handler, capture, passive) {
} }
} }
// Chrome has a bug where pointer events don't work when attached to a DOM element that has been cloned
// with cloneNode() and the DOM element is disconnected from the document. To ensure the event works, we
// defer the attachment till after it's been appended to the document. TODO: remove this once Chrome fixes
// this bug.
if (event_name.startsWith('pointer')) {
queue_task(() => {
dom.addEventListener(event_name, target_handler, options); dom.addEventListener(event_name, target_handler, options);
});
} else {
dom.addEventListener(event_name, target_handler, options);
}
return target_handler;
}
/**
* @param {string} event_name
* @param {Element} dom
* @param {EventListener} handler
* @param {boolean} capture
* @param {boolean} [passive]
* @returns {void}
*/
export function event(event_name, dom, handler, capture, passive) {
var options = { capture, passive };
var target_handler = create_event(event_name, dom, handler, options);
// @ts-ignore // @ts-ignore
if (dom === document.body || dom === window || dom === document) { if (dom === document.body || dom === window || dom === document) {

Loading…
Cancel
Save