Problem/Motivation
While working on #2998091-66: Remote videos overflow their containing element, the question was raised if we should allow JavaScript to be attached inside the oEmbed content iframe. That issue disallowed it in order to keep the scope limited, but we agreed to open this follow-up issue to discuss and possibly implement the ability to attach JavaScript too.
Themers need a way to interact and control oEmbed content. For example, if there is a play button next to a Vimeo video the JavaScript on the parent page must send the play request through the parent iframe to the child iframe. The child iframe page (media-oembed-iframe.html.twig) must be able to have JavaScript in order to receive the play request from the parent iframe and send it to the child iframe. (It is not possible use Window.postMessage() through multiple iframes.) Both Drupal JavaScript and external JavaScript should be allowed since the provider’s JavaScript API (//player.vimeo.com/api/player.js in this example) will be needed.
Proposed resolution
This is possible once #3230772: OembedMediaController doesn't properly bubble cacheability metadata/attachments lands, at which point we can document how to achieve this functionality.
Most likely in the Twig file.
Remaining tasks
TBD.
User interface changes
TBD, but probably none.
API changes
TBD, probably none.
Data model changes
None.
Release notes snippet
TBD
Comments
Comment #2
phenaproximaComment #3
phenaproximaThe blocker is in, so this is no longer postponed.
Comment #4
rajab natshahThanks for opening this issue
I think the final media-oembed-iframe.html.twig could look as followes:
I'm posing a spaghetti code which still under optimization for a Case Scenario example, which we require
autoplay a video when we click on the cover image, or autoplay when the slide goes to the next slide.
Still some other issues. of letting the child iframe send a message of ended to let the slider go to the next slide for example
I think if the issue of sending the provider to the twig is fixed
It could let us have twig for each remote provider with custom JS attache of remote or local libraries.
or other ways of preprocessing.
My questions at this time:
when we switch to use
<js-placeholder token="{{ placeholder_token }}">Comment #5
rajab natshahIf we #3044967: Add [Provider name] to the OEmbed Iframe Controller to let themers have the option of knowing which provider in media oembed iframe template or the pre-processor theme suggestion alter
we could use that in something like the following for
filtaring or flaging libraries when we swich to placeholders
We could change to use
with something like
Comment #6
wim leersThis has security and front-end performance implications: it'll result in more JS being loaded on the front end.
I'm also not seeing in the issue summary why this is desirable: what things does it enable that are not possible today?
Finally, I'm assuming we're talking only about Drupal-owned JS, not external JS, right?
Comment #7
phenaproximaComment #9
daniel korte@Wim Leers I updated the Why in the summary. Hopefully it makes sense.
We need both Drupal-owned JS and external JS to be allowed here.
Comment #13
osab commentedHi!
I want to share enough rough trick to make autoplay video inside child iframe. I hope we can use more correct approach to achieve the same further.
So, the case is we have separate preview image for media video item with custom designed play button. And when we click on the play button we need to open and autostart youtube video. But by default we can to set "autoplay=1" attribute to the parent iframe only and we have to click play button in the second time on the youtube child iframe.
The main idea to solve this problem is to use video code and load youtube in JS directly, instead of using default {{ media|raw }} from media-oembed-iframe.html.twig. It was inspired by https://codepen.io/tutsplus/pen/RRVRro.
Here is detailed description:
- media-oembed-iframe.html.twig:
- media field template contains our custom button:
- on the next step we need to prepare video url on media field preprocess hook:
Here we can set different URLs for different providers:
- loading child iframe in js by click on play-button:
Video URL with autoplay are in data_embed_url.
Hope it will help someone. :)
Comment #14
larowlanThere's a bug in how the controller works that is preventing addition of Javascript but also CSS and any cacheability metadata.
#3230772: OembedMediaController doesn't properly bubble cacheability metadata/attachments
With that, you could add JS in the preprocess hook like so - example is adding GTM to
$variables['#attached'], but you could equally do$variables['#attached']['library'][] = 'some/library';Comment #15
larowlanComment #16
larowlanIn my opinion, we should just fix that bug, and then close this as it would be possible with the existing tools.
Comment #17
ac@larowlan
Could you provide an example of how to load a library using this method? I have applied your patch in the other issue and can rewrite the $variables['media'] string but am not able to load a library in the iframe.Looking further into it, my library is being loaded using $variables['#attached']['library'][] = 'foo/bar', however only the CSS is being rendered, not the JS. Any suggestions on how to get that to load?
Comment #18
larowlanYeah the hook above + this in the twig template:
in the
<head>elementComment #19
acThanks. That is what I was doing but with no luck. Have you successfully done this? I am guessing your example is likely a real implementation.
Comment #20
larowlanYeah hook + patch + twig file is working for me in a production site
Comment #21
larowlanI also have the patch from #3230547: \Drupal\media\Controller\OEmbedIframeController::render doesn't set a content-type header on this project, that might be significant, but I doubt it
Comment #22
acThis is what I have (and many other variations on this)
foo.theme
foo.libraries.yml
templates/media/media-oembed-iframe.html.twig
When the oembed item is rendered this is what I get in the head of the iframe
I was expecting to also see js/play.js loaded.
Comment #23
larowlanYeah, that's consistent with how I've got it working 🤔
Comment #24
acVery odd. Are you running any other core patches?
Comment #25
larowlanQuite a few, but none that stand out as being relevant.
If you're on slack, feel free to ping me there (same username) and I can share a URL where I've got it running - I just checked and it does add the JS from Google Tag manager (which is what I was trying to achieve).
Comment #26
acFollow up to #22 with a working solution:
foo.libraries.yml needs to force the js to load in the header and not the default which is the footer:
Doing this along with the rest of #22 now lets me load both CSS and JS from a theme library in the oembed iframe. Thanks to @larowlan for the help and guidance.
Comment #27
acThis also means that this issue can probably be closed (I will let someone else do that) and #3230772: OembedMediaController doesn't properly bubble cacheability metadata/attachments should be committed. In doing this we have a clean way of adding JS to the oembed iframe.
Comment #28
larowlanRather than closing this issue, let's make it about documenting how to achieve this.
Postponing on #3230772: OembedMediaController doesn't properly bubble cacheability metadata/attachments
Comment #29
mstrelan commented