-
Notifications
You must be signed in to change notification settings - Fork 3.9k
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
✨Add amp-iframe support for Pym.js width and height resize messages #24917
✨Add amp-iframe support for Pym.js width and height resize messages #24917
Conversation
@@ -466,6 +466,8 @@ export class AmpIframe extends AMP.BaseElement { | |||
/*opt_allowOpaqueOrigin*/ true | |||
); | |||
|
|||
addEventListener('message', this.listenForPymMessage_.bind(this)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems not ideal. There should rather be one single message
event handler that all of the iframes share.
It seems rather that listenFor
should be used, but the problem is that the Pym.js event.data
is a string and not an object with any sentinel
. So there isn't an easy way to integrate with this existing event listener system.
this.updateSize_(parseInt(args[1], 10), undefined); | ||
} else if ('width' === args[0]) { | ||
this.updateSize_(undefined, parseInt(args[1], 10)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps a message should be logged out for other message types so that a developer doesn't get confused about why it is not working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. We could do a user().warn()
for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 197c110
c15556e
to
231d8fe
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Couple minor comments. And this will need tests.
@@ -103,6 +103,9 @@ export class AmpIframe extends AMP.BaseElement { | |||
/** @private {string} */ | |||
this.sandbox_ = ''; | |||
|
|||
/** @private {Function} */ | |||
this.unlisten_ = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's name it unlistenPym_
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 0b31cca
@@ -466,6 +469,13 @@ export class AmpIframe extends AMP.BaseElement { | |||
/*opt_allowOpaqueOrigin*/ true | |||
); | |||
|
|||
// Listen for resize messages sent by Pym.js. | |||
this.unlisten_ = listen( | |||
window, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/window/this.win
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 89dcadb
* Listen for Pym.js messages for 'height' and 'width'. | ||
* | ||
* @see http://blog.apps.npr.org/pym.js/ | ||
* @param {MessageEvent} event |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!MessageEvent
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.updateSize_(parseInt(args[1], 10), undefined); | ||
} else if ('width' === args[0]) { | ||
this.updateSize_(undefined, parseInt(args[1], 10)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure. We could do a user().warn()
for this.
c3fa98c
to
761267d
Compare
Tests added in 3a726ba. |
I'm not sure why the tests are failing, as the failures don't seem related to my code. Nevertheless, I wasn't able to get the tests working locally either (even on Cf. Slack thread |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code LGTM. The test failures seem superficially relevant. But could be something else. I'll take a look as well.
6d2fe10
to
92604a4
Compare
test/fixtures/served/iframe.html
Outdated
} else if (event.data.type === 'requestPymjsHeight') { | ||
var msg = [ 'pym', 'height', event.data.height ].join( 'xPYMx' ); | ||
getAmpWindow(sentinel)./*OK*/postMessage( msg, '*'); | ||
} else if (event.data.type === 'requestPymjsWidth') { | ||
var msg = [ 'pym', 'width', event.data.height ].join( 'xPYMx' ); | ||
getAmpWindow(sentinel)./*OK*/postMessage( msg, '*'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sentinel
I believe is undefined
here, so that's not right. Nevertheless, I've tried populating sentinel
here I tried populating with event.data.sentinel
and 'amp'
and 'amp-test'
but no success.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. I'll try to take a look tomorrow, but I'm running out of time a bit. Could you ping @jridgewell to see if he might have advise on messaging specifically for tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sentinel
variable was indeed undefined
. This seems to be part of the problem; the var
was hoisting so the undefinedness wasn't causing an error. Fixed in c640f88.
return; | ||
} | ||
const data = getData(event); | ||
if (typeof data !== 'string' || 'pym' !== data.substr(0, 3)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a startsWith
helper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Utilized in af98c22
return; | ||
} | ||
|
||
// The format of the message takes the form of `pym${id}xPYMx${type}xPYMx${message}`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The format has a "xPYMx" between "pymand
${id}`, too. That was confusing me since you were splicing 2 elements from the front of the array (without the "xPYMx" there, you would be splicing too much).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Fixed in eafb57a
// 'height', 'width', 'parentPositionInfo', 'navigateTo', and 'scrollToChildPos'. | ||
// Only the 'height' and 'width' messages are currently supported. | ||
// See <https://github.com/nprapps/pym.js/blob/57feb68/src/pym.js#L85-L102> | ||
const args = data.split(/xPYMx/).splice(2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: no need to splice, just reference indexes 2 and 3.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in eafb57a
test/fixtures/served/iframe.html
Outdated
@@ -52,6 +52,12 @@ | |||
sentinel: sentinel, | |||
type: 'send-embed-state', | |||
}, '*'); | |||
} else if (event.data.type === 'requestPymjsHeight') { | |||
var msg = [ 'pym', 'height', event.data.height ].join( 'xPYMx' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to add some bogus id
after pym
and before height
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 2d578da
test/fixtures/served/iframe.html
Outdated
var msg = [ 'pym', 'height', event.data.height ].join( 'xPYMx' ); | ||
getAmpWindow(sentinel)./*OK*/postMessage( msg, '*'); | ||
} else if (event.data.type === 'requestPymjsWidth') { | ||
var msg = [ 'pym', 'width', event.data.height ].join( 'xPYMx' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 2d578da
Ready for review? |
Yes, I was just waiting for the jobs to finish before re-requesting. But yes! |
dc41fe8
to
bc04025
Compare
Rebased to re-trigger build due to infra issue. |
Fixes #22714.
Pym.js supports the client window sending several types of messages, including:
height
width
parentPositionInfo
navigateTo
scrollToChildPos
The only two messages that seem relevant in an AMP context are
width
andheight
, as they map to theembed-size
message that AMP is currently looking for.Demo video (YouTube):
The code can be tested using this Glitch: https://amp-iframe-pymjs-resizable.glitch.me/