Responsive TinyMCE YouTube

Web Development
3rd November 2022 Responsive TinyMCE YouTube

Before TinyMCE Cloud, I edited the core files I downloaded to ensure that YouTube iframes were wrapped in a div. Things changed with TinyMCE Cloud, so I've had a bit of a rethink on how I've done things.

I never really like editing core files. If I can leave them alone, then great. I want updates to be as smooth and simple as possible. That's why I chose to use TinyMCE Cloud instead of staying on an older version. But that left me wondering how to wrap any YouTube videos into a responsive div.

Option One: Custom Button

My first thought was to make a custom button. That brings up a modal that contains a text box, and from there, I paste in the iframe-embedded code. Just create the modal window and replace the media button in your taskbar with a new button.

It's fine but has some drawbacks. The first is that, ideally, I'd like to use native buttons instead of having to create my own. Secondly, on YouTube you have to click Share and then Embed, then copy the whole iframe code into the modal.

var dialogMedia =  {
  title: 'Embed Media',
  body: {
	type: 'panel',
	items: [
	  {
		type: 'textarea',
		name: 'linkText',
		label: 'Paste embed code'
	  }
	]
  },
  buttons: [
	{
	  type: 'cancel',
	  name: 'closeButton',
	  text: 'Cancel'
	},
	{
	  type: 'submit',
	  name: 'submitButton',
	  text: 'Add Media',
	  primary: true
	}
  ],
  onSubmit: function (api) {
	var data = api.getData();
	tinymce.activeEditor.execCommand('mceInsertContent', false, '<div class="ratio ratio-16x9 mb-4"> '+ data.linkText + '</div><p>&nbsp;</p>');
	api.close();
  }
};

Thankfully, there's a better way. And with a few tweaks, you can just copy the YouTube URL.

Option Two: Using media_url_resolver

TinyMCE has a media_url_resolver option. Here, you check if the URL of a media insert includes YouTube. If it does, then add a wrapper div around the iframe.

Before adding the wrapper frame, though, a new line needs to be added. I mentioned just pasting the YouTube URL for quickness. Without this additional line, you'll have a video that doesn't work. That is because the YouTube URL does not include "embed", which it needs when playing away from YouTube.

To get around that, we need to change the data.url that we paste into TinyMCE. Thankfully, the only difference between a YouTube URL and a YouTube embed URL is one part in the middle. You just need to add a Javascript replace to swap out "watch?v=" with "embed/", and you have a URL that works with TinyMCE.

media_url_resolver: function (data, resolve) {
        if (data.url.indexOf('youtube') !== -1) {   
          data.url = data.url.replace("watch?v=", "embed/");
          var embedHtml = '<div class="ratio ratio-16x9 mb-4"><iframe title="YouTube video player" src="' + data.url + '" width="560" height="315" frameborder="0"></iframe></div>';
          resolve({ html: embedHtml });
        } else {
          // use the tinymce default template (passing empty string in the html makes tinymce to use the default)
          resolve({ html: '' });
        }
},

And that produces a working YouTube video with TinyMCE that is responsive - or can be made responsive with your own wrapper div.

The best part is that there are no core TinyMCE changes. It's all part of the TinyMCE initialisation, using the standard media plugin.

* Both examples work on wrapping the div in a responsive container, similar to how Bootstrap handles iFrames.