Skip to content

Commit

Permalink
🐛 [amp-carousel 0.2] Stop propagation of touchmove event to viewer (#…
Browse files Browse the repository at this point in the history
…33444)

Co-authored-by: Kristofer Baxter <kristofer@kristoferbaxter.com>
  • Loading branch information
Micajuine Ho and kristoferbaxter committed Mar 23, 2021
1 parent 843d597 commit 2d01a12
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
19 changes: 18 additions & 1 deletion extensions/amp-carousel/0.2/amp-carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
dispatchCustomEvent,
} from '../../../src/dom';
import {computedStyle} from '../../../src/style';
import {createCustomEvent, getDetail} from '../../../src/event-helper';
import {createCustomEvent, getDetail, listen} from '../../../src/event-helper';
import {dev, devAssert, userAssert} from '../../../src/log';
import {dict} from '../../../src/utils/object';
import {htmlFor} from '../../../src/static-template';
Expand Down Expand Up @@ -129,6 +129,9 @@ class AmpCarousel extends AMP.BaseElement {
* @private {boolean}
*/
this.showControls_ = false;

/** If the ampdoc is in the Viewer */
this.isViewerEmbeded_ = Services.viewerForDoc(element).isEmbedded();
}

/** @override */
Expand Down Expand Up @@ -175,6 +178,7 @@ class AmpCarousel extends AMP.BaseElement {
);
this.prevButton_.addEventListener('click', () => this.interactionPrev());
this.nextButton_.addEventListener('click', () => this.interactionNext());
this.handlePropagationInViewer_();

const owners = Services.ownersForDoc(element);
this.childLayoutManager_ = new ChildLayoutManager({
Expand Down Expand Up @@ -632,6 +636,19 @@ class AmpCarousel extends AMP.BaseElement {
);
}

/**
* Attach singal onto touchmove event to stop propagation to viewer
* to be handled at the viewer integration layer in bubble phase.
*/
handlePropagationInViewer_() {
if (!this.isViewerEmbeded_) {
return;
}
listen(this.scrollContainer_, 'touchmove', (event) => {
event.shouldViewerCancelPropagation = true;
});
}

/**
* Toggles the current autoplay state, or forces it if the enable
* argument is given.
Expand Down
31 changes: 31 additions & 0 deletions extensions/amp-carousel/0.2/test/test-type-slides.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
*/

import '../amp-carousel';
import * as Listen from '../../../../src/event-helper';
import {ActionTrust} from '../../../../src/action-constants';
import {CarouselEvents} from '../../../amp-base-carousel/0.1/carousel-events';
import {Services} from '../../../../src/services';
import {getDetail, listenOncePromise} from '../../../../src/event-helper';

/**
Expand Down Expand Up @@ -529,5 +531,34 @@ describes.realWin(
});
});
});

describe('event propogation', () => {
it('should add touchmove event if in viewer', async () => {
env.sandbox.stub(Services, 'viewerForDoc').returns({
isEmbedded: () => {
return true;
},
});
const listenSpy = env.sandbox.spy(Listen, 'listen');
const carousel = await getCarousel({loop: false});
const impl = await carousel.getImpl();

expect(listenSpy.lastCall.args[0]).to.equal(impl.scrollContainer_);
expect(listenSpy.lastCall.args[1]).to.equal('touchmove');
expect(listenSpy.args.length).to.equal(5);
});

it('should not add touchmove event if not in the viewer', async () => {
env.sandbox.stub(Services, 'viewerForDoc').returns({
isEmbedded: () => {
return false;
},
});
const listenSpy = env.sandbox.spy(Listen, 'listen');
await getCarousel({loop: false});

expect(listenSpy.args.length).to.equal(4);
});
});
}
);
17 changes: 17 additions & 0 deletions extensions/amp-viewer-integration/0.1/test/test-touch-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,23 @@ describes.fakeWin('TouchHandler', {}, (env) => {
expect(messages[0].data.data.type).to.equal('touchstart');
});

it('should not forward events marked with `shouldViewerCancelPropagation`', () => {
const event = fakeTouchEvent('touchmove');
event.stopImmediatePropagation = env.sandbox.spy();

touchHandler.handleEvent_(event);
expect(messages).to.have.length(1);
expect(messages[0].data.data.type).to.equal('touchmove');
expect(event.stopImmediatePropagation).to.not.be.called;

event.shouldViewerCancelPropagation = true;
messages = [];
touchHandler.handleEvent_(event);

expect(messages).to.have.length(0);
expect(event.stopImmediatePropagation).to.be.calledOnce;
});

it('should lock scrolling', () => {
expect(unlistenCount).to.equal(0);
expect(listeners).to.have.length(3);
Expand Down
4 changes: 4 additions & 0 deletions extensions/amp-viewer-integration/0.1/touch-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ export class TouchHandler {
* @private
*/
forwardEvent_(e) {
if (e && e.shouldViewerCancelPropagation) {
e.stopImmediatePropagation();
return;
}
if (e && e.type) {
const msg = this.copyTouchEvent_(e);
this.messaging_.sendRequest(e.type, msg, false);
Expand Down

0 comments on commit 2d01a12

Please sign in to comment.