Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(esl-carousel): fix handling of pointercancel event by touch plugin #2487

Merged
merged 4 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions site/views/examples/carousel/vertical.sample.njk
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: Vertical Carousel (Single)
order: 4
tags: carousel-sample
---

<div class="esl-carousel-no-extra-space" esl-carousel-container>
<button class="esl-carousel-arrow inner prev hide-xs" esl-carousel-nav="group:prev">
<span class="sr-only">Previous Slide</span>
</button>

<esl-carousel demo-options-target
style="aspect-ratio: 16 / 9"
esl-carousel-touch="swipe"
vertical
loop="true">
<ul esl-carousel-slides>
{% for i in range(0, 4) -%}
<li esl-carousel-slide>
<div class="card">
<div class="img-container img-container-16-9">
<esl-image mode="cover" lazy
data-alt="Alt Text Test"
data-src="{{ '/assets/carousel/' + loop.index + '-sm.jpg' | url }}"></esl-image>
<div class="h1 text-slide text-white">Slide {{ loop.index }}</div>
</div>
</div>
</li>
{%- endfor %}
</ul>
</esl-carousel>

<button class="esl-carousel-arrow inner next hide-xs" esl-carousel-nav="group:next">
<span class="sr-only">Next Slide</span>
</button>

<esl-carousel-dots class="carousel-dots-wrapper"></esl-carousel-dots>

<style>
.text-slide {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</div>
2 changes: 2 additions & 0 deletions src/modules/esl-base-element/core/esl-base-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export abstract class ESLBaseElement extends HTMLElement implements ESLBaseCompo
return this._connected;
}

/** Subscribes (or resubscribes) all known descriptors that matches criteria */
public $$on(criteria: ESLListenerCriteria): ESLEventListener[];
/** Subscribes `handler` method marked with `@listen` decorator */
public $$on(handler: ESLListenerHandler): ESLEventListener[];
/** Subscribes `handler` function by the passed DOM event descriptor {@link ESLListenerDescriptor} or event name */
Expand Down
21 changes: 8 additions & 13 deletions src/modules/esl-carousel/plugin/touch/esl-carousel.touch.mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin {
/** Defines distance tolerance to swipe */
@attr({name: 'esl-carousel-swipe-distance', defaultValue: 20, parser: parseInt}) public swipeDistance: number;
/** Defines timeout tolerance to swipe */
@attr({name: 'esl-carousel-swipe-timeout', defaultValue: 2000, parser: parseInt}) public swipeTimeout: number;
@attr({name: 'esl-carousel-swipe-timeout', defaultValue: 400, parser: parseInt}) public swipeTimeout: number;

/** Start pointer event to detect action */
protected startEvent?: PointerEvent;
Expand Down Expand Up @@ -85,6 +85,7 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin {

/** @returns offset between start point and passed event point */
protected getOffset(event: PointerEvent): number {
if (event.type === 'pointercancel') return 0;
const property = this.$host.config.vertical ? 'clientY' : 'clientX';
return this.startEvent ? (event[property] - this.startEvent[property]) : 0;
}
Expand All @@ -106,12 +107,11 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin {
this.startEvent = event;
this.startScrollOffsets = getParentScrollOffsets(event.target as Element, this.$host);

this.$$on('pointermove', this._onPointerMove);
this.$$on('pointerup pointercancel', this._onPointerUp);
this.$$on({group: 'pointer'});
}

/** Processes `mousemove` and `touchmove` events. */
@listen({auto: false})
@listen({auto: false, event: 'pointermove', group: 'pointer'})
protected _onPointerMove(event: PointerEvent): void {
const offset = this.getOffset(event);

Expand All @@ -129,11 +129,10 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin {
}

/** Processes `mouseup` and `touchend` events. */
@listen({auto: false})
@listen({auto: false, event: 'pointerup pointercancel', group: 'pointer'})
protected _onPointerUp(event: PointerEvent): void {
// Unbinds drag listeners
this.$$off(this._onPointerMove);
this.$$off(this._onPointerUp);
this.$$off({group: 'pointer'});

if (this.$host.hasPointerCapture(event.pointerId)) {
this.$host.releasePointerCapture(event.pointerId);
Expand All @@ -142,17 +141,13 @@ export class ESLCarouselTouchMixin extends ESLCarouselPlugin {
if (this.$$attr('dragging', false) === null) return;

const offset = this.getOffset(event);
// ignore single click
if (offset === 0) return;
// Commit drag offset
// Commit drag offset (should be commited to 0 if the event is canceled)
if (this.isDragMode) this.$host.renderer.commit(offset);
// Swipe final check
if (this.isSwipeMode && !this.isPrevented && this.isSwipeAccepted(event)) {
if (this.isSwipeMode && offset && !this.isPrevented && this.isSwipeAccepted(event)) {
const target = `${this.swipeType}:${offset < 0 ? 'next' : 'prev'}`;
if (this.$host.canNavigate(target)) this.$host.goTo(target);
}

delete this.startEvent;
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/modules/esl-mixin-element/ui/esl-mixin-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export class ESLMixinElement implements ESLBaseComponent, ESLDomElementRelated {
*/
protected attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {}

/** Subscribes (or resubscribes) all known descriptors that matches criteria */
public $$on(criteria: ESLListenerCriteria): ESLEventListener[];
/** Subscribes `handler` method marked with `@listen` decorator */
public $$on(handler: ESLListenerHandler): ESLEventListener[];
/** Subscribes `handler` function by the passed DOM event descriptor {@link ESLListenerDescriptor} or event name */
Expand Down
2 changes: 2 additions & 0 deletions src/modules/esl-utils/abstract/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import type {
} from '../../esl-event-listener/core';

export interface ESLBaseComponent {
/** Subscribes (or resubscribes) all known descriptors that matches criteria */
$$on(criteria: ESLListenerCriteria): ESLEventListener[];
/** Subscribes `handler` method marked with `@listen` decorator */
$$on(handler: ESLListenerHandler): ESLEventListener[];
/** Subscribes `handler` function by the passed DOM event descriptor {@link ESLListenerDescriptor} or event name */
Expand Down
Loading