diff --git a/docs/building-a-bento-iframe-component.md b/docs/building-a-bento-iframe-component.md index c627ee6d4af5..af5df15d839b 100644 --- a/docs/building-a-bento-iframe-component.md +++ b/docs/building-a-bento-iframe-component.md @@ -233,7 +233,7 @@ function FantasticEmbedWithRef({...rest}, ref) { AMP documents additionally guarantee layout stability to the degree that it manages when components may or may not resize on the page. Because of this, the `IframeEmbed` component takes a `requestResize` prop where a different flow of logic may be passed in by the publisher to respond to measure events. -In your AMP element implementation, you will use `requestResize` to pass in the `attemptChangeHeight` method that is extended from the `BaseElement` class: +In your AMP element implementation, you will use `requestResize` to pass in the `attemptChangeHeight` method that is extended from the `PreactBaseElement` class: ```javascript // amp-fantastic-embed.js @@ -242,14 +242,23 @@ class AmpFantasticEmbed extends BaseElement { /** @override */ init() { return dict({ - 'requestResize': (height) => { - this.attemptChangeHeight(height); - }, + 'requestResize': (height) => this.attemptChangeHeight(height), }); } } ``` +For components that request a resize that is denied by the AMP runtime, publishers are recommended to use an `overflow` element to solicit user interaction in order to resize as a layout stability best-practice. + +This information can be provided in the component documentation with an exemplary code sample: + +```html + + + +

Content below the component.

+``` + #### Passing or overriding props In the previous example, props received from the `ProxyIframeEmbed` are implicitly set through `...rest`. If we set each explicitly, we see the `HTMLIframeElement` attributes handled. diff --git a/extensions/amp-facebook/1.0/amp-facebook.js b/extensions/amp-facebook/1.0/amp-facebook.js index d5d9d093dc16..2b5f5f4dd900 100644 --- a/extensions/amp-facebook/1.0/amp-facebook.js +++ b/extensions/amp-facebook/1.0/amp-facebook.js @@ -54,7 +54,7 @@ class AmpFacebook extends BaseElement { init() { return dict({ 'onReady': () => this.togglePlaceholder(false), - 'requestResize': (height) => this.forceChangeHeight(height), + 'requestResize': (height) => this.attemptChangeHeight(height), }); } diff --git a/extensions/amp-facebook/1.0/test/test-amp-facebook.js b/extensions/amp-facebook/1.0/test/test-amp-facebook.js index 13d35a272ea5..5f23c1768141 100644 --- a/extensions/amp-facebook/1.0/test/test-amp-facebook.js +++ b/extensions/amp-facebook/1.0/test/test-amp-facebook.js @@ -1,5 +1,5 @@ /** - * Copyright 2015 The AMP HTML Authors. All Rights Reserved. + * Copyright 2021 The AMP HTML Authors. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -286,7 +286,11 @@ describes.realWin( await waitForRender(); const impl = await element.getImpl(false); - const forceChangeHeightStub = env.sandbox.stub(impl, 'forceChangeHeight'); + const attemptChangeHeightStub = env.sandbox.stub( + impl, + 'attemptChangeHeight' + ); + attemptChangeHeightStub.returns(Promise.resolve()); const mockEvent = new CustomEvent('message'); const sentinel = JSON.parse( @@ -298,7 +302,7 @@ describes.realWin( mockEvent.source = element.shadowRoot.querySelector('iframe').contentWindow; win.dispatchEvent(mockEvent); - expect(forceChangeHeightStub).to.be.calledOnce.calledWith(1000); + expect(attemptChangeHeightStub).to.be.calledOnce.calledWith(1000); }); } ); diff --git a/extensions/amp-instagram/1.0/amp-instagram.js b/extensions/amp-instagram/1.0/amp-instagram.js index 933af96f3175..093e3cc89ffb 100644 --- a/extensions/amp-instagram/1.0/amp-instagram.js +++ b/extensions/amp-instagram/1.0/amp-instagram.js @@ -37,9 +37,7 @@ class AmpInstagram extends BaseElement { /** @override */ init() { return dict({ - 'requestResize': (height) => { - this.forceChangeHeight(height); - }, + 'requestResize': (height) => this.attemptChangeHeight(height), }); } } diff --git a/extensions/amp-instagram/1.0/test/test-amp-instagram.js b/extensions/amp-instagram/1.0/test/test-amp-instagram.js index 9d2003784c7c..71170e58b60b 100644 --- a/extensions/amp-instagram/1.0/test/test-amp-instagram.js +++ b/extensions/amp-instagram/1.0/test/test-amp-instagram.js @@ -93,7 +93,11 @@ describes.realWin( await waitForRender(); const impl = await element.getImpl(false); - const forceChangeHeightStub = env.sandbox.stub(impl, 'forceChangeHeight'); + const attemptChangeHeightStub = env.sandbox.stub( + impl, + 'attemptChangeHeight' + ); + attemptChangeHeightStub.returns(Promise.resolve()); const mockEvent = new CustomEvent('message'); mockEvent.origin = 'https://www.instagram.com'; @@ -107,7 +111,7 @@ describes.realWin( element.shadowRoot.querySelector('iframe').contentWindow; win.dispatchEvent(mockEvent); - expect(forceChangeHeightStub).to.be.calledOnce.calledWith(1000); + expect(attemptChangeHeightStub).to.be.calledOnce.calledWith(1000); }); } ); diff --git a/extensions/amp-twitter/1.0/amp-twitter.js b/extensions/amp-twitter/1.0/amp-twitter.js index 5005bd591234..5fcd010cd389 100644 --- a/extensions/amp-twitter/1.0/amp-twitter.js +++ b/extensions/amp-twitter/1.0/amp-twitter.js @@ -74,7 +74,7 @@ class AmpTwitter extends BaseElement { /** @override */ init() { return dict({ - 'requestResize': (height) => this.forceChangeHeight(height), + 'requestResize': (height) => this.attemptChangeHeight(height), }); } diff --git a/extensions/amp-twitter/1.0/test/test-amp-twitter.js b/extensions/amp-twitter/1.0/test/test-amp-twitter.js index eed71423b540..eed335fe9b58 100644 --- a/extensions/amp-twitter/1.0/test/test-amp-twitter.js +++ b/extensions/amp-twitter/1.0/test/test-amp-twitter.js @@ -74,7 +74,11 @@ describes.realWin( await waitForRender(); const impl = await element.getImpl(false); - const forceChangeHeightStub = env.sandbox.stub(impl, 'forceChangeHeight'); + const attemptChangeHeightStub = env.sandbox.stub( + impl, + 'attemptChangeHeight' + ); + attemptChangeHeightStub.returns(Promise.resolve()); const mockEvent = new CustomEvent('message'); const sentinel = JSON.parse( @@ -86,7 +90,7 @@ describes.realWin( mockEvent.source = element.shadowRoot.querySelector('iframe').contentWindow; win.dispatchEvent(mockEvent); - expect(forceChangeHeightStub).to.be.calledOnce.calledWith(1000); + expect(attemptChangeHeightStub).to.be.calledOnce.calledWith(1000); }); it('should replace iframe after tweetid mutation', async () => { diff --git a/src/preact/base-element.js b/src/preact/base-element.js index 3b6e16eda342..904769ed8e07 100644 --- a/src/preact/base-element.js +++ b/src/preact/base-element.js @@ -382,6 +382,19 @@ export class PreactBaseElement extends AMP.BaseElement { } } + /** @override */ + attemptChangeHeight(newHeight) { + return super.attemptChangeHeight(newHeight).catch((e) => { + if (this.getOverflowElement && !this.getOverflowElement()) { + console./* OK */ warn( + '[overflow] element not found. Provide one to enable resizing to full contents.', + this.element + ); + } + throw e; + }); + } + /** * @protected * @param {!JsonObject} props