Opened 11 years ago
Closed 10 years ago
#28190 closed defect (bug) (fixed)
Support for mediaelement.js YouTube sources in the video shortcode does not work in TinyMce
Reported by: | Fab1en | Owned by: | |
---|---|---|---|
Milestone: | 4.0 | Priority: | normal |
Severity: | normal | Version: | 3.9 |
Component: | Media | Keywords: | has-patch |
Focuses: | javascript, administration | Cc: |
Description
When using a youtube URL within a video shortcode, the mediaelement.js player does not work inside TinyMce. It does work on the front end, or when the "Edit" button of the mceView is clicked.
[video src="http://www.youtube.com/watch?v=yeJYVzLFLhk"]
Inside TinyMce, it shows the row URL, as if the URL was not recognized as a video one.
Attachments (5)
Change History (17)
#3
@
11 years ago
So the problem here is that youtube
isn't assigned to the compat
var as a compatible video type for any of the browsers. The diff I uploaded fixes that.
I was initially concerned about specifying youtube and not any other video services, but I noticed that the same thing is done on the front end. See line 1803
in wp-includes/media.php
. YouTube is specified separately to other video mime types, as it is all over wp-includes/media-template.php
.
At this point the problem was resolved, but I did notice a display error in the way the media element was being rendered inside tinymce. I managed to track this down to a bug in wp-includes/media-template.php
. Line 63 was using the variable h
before it had been assigned. This is also included in the diff.
That fixed a display issue, but YouTube embeds still looked wrong (they displayed the YouTube video controls, instead of the mediaelement video controls). I believe that this is related to a Javascript error that now occurs:
ReferenceError: Can't find variable: mejs
Unfortunately this error is not linked to a javascript file (maybe it's being done via eval
?), and I've searched for hours but have been unable to fix it.
#4
@
11 years ago
Thanks lukecarbis for this patch. Detecting youtube video using the mime type is cleaner than parsing the url, this should be the way to do it in all other places, and would allow easier addition for other providers (Vimeo, Dailymotion, ...).
I have also seen the Javascript error you mentioned. I managed to understand from where it comes from : the javascript code is executed by the MediaElementJS flash bridge to create a javascript event. (see line 1020 in src/flash/FlashMediaElement.as https://github.com/johndyer/mediaelement/blob/master/src/flash/FlashMediaElement.as#L1020 of MediaElementJS source code). The flash code assumes that mejs
is a global var holding the library, but inside TinyMce iframe this global var is not defined. You can remove the javascript error by executing the following code in the console before inserting the shortcode :
window.frames[0].mejs = mejs
But this will not remove the youtube video display issue. This issue is caused by something else. You can see by inspecting the generated DOM that MEJS control bar is present but empty. Something must prevent controls from being generated, but I could not determine what. Perhaps nesting iframes raise an issue ? Or perhaps it is a race condition between youtube iframe loading and tinyMce iframe ?
The youtube video play control is displayed by the youtube iframe, so it cannot be removed. It is also present in the well generated mejs player that shows when you click on the edit button of the video shortcode.
#5
@
11 years ago
window.frames[0].mejs = mejs
is clever, but TinyMCE doesn't seem to let <embed>
s play. So, you can get the YouTube via <embed>
to display, but that's it.
We don't have to solve this immediately, let's keep working at it.
28190.diff combines all the info we currently have.
#6
@
10 years ago
I dug a little bit more into the JS code, and I found that the YouTube embedded player inside MediaElementJS is not playing because the MediaElementJS controls are not built. And MediaElementJS controls are not built, because success
callback is not called.
success
callback is called here in MediaElementJS :
// when Flash/Silverlight is ready, it calls out to this method initPlugin: function (id) { var pluginMediaElement = this.pluginMediaElements[id], htmlMediaElement = this.htmlMediaElements[id]; if (pluginMediaElement) { // find the javascript bridge switch (pluginMediaElement.pluginType) { case "flash": pluginMediaElement.pluginElement = pluginMediaElement.pluginApi = document.getElementById(id); break; case "silverlight": pluginMediaElement.pluginElement = document.getElementById(pluginMediaElement.id); pluginMediaElement.pluginApi = pluginMediaElement.pluginElement.Content.MediaElementJS; break; } if (pluginMediaElement.pluginApi != null && pluginMediaElement.success) { pluginMediaElement.success(pluginMediaElement, htmlMediaElement); } } },
The buggy part is here : document.getElementById(id);
document
is a global var that points to the main window document instead of the iframe one. That's why the id
is not found and therefore the callback cannot be executed.
If I replace
document.getElementById(id);
by
window.frames['content_ifr'].document.getElementById(id)
then the player works fine inside TinyMce
Now I need to figure out how to do this properly.
#7
@
10 years ago
- Keywords has-patch added; needs-patch removed
I finally understood the root cause of the issue : the mediaelementjs javascript must be loaded inside the tinymce iframe to make it work properly (just like mediaelement css is already loaded inside the iframe).
Several scripts must be loaded, with respects for dependencies, so we must must wait for a script to be fully loaded before proceeding with the next one.
I have modified the patch to take this into account. I would appreciate to have your opinion.
#9
@
10 years ago
28190.2.diff retools some of this. I can imagine @azaozz will hate every bit of it, but the loading of MEjs in the TinyMCE iframe would allow us to ditch tons of compat checking code. Also, makes [video]
work with YouTube as the source.
I think the
wp.media.mixin.isCompatible
function is the one to blame here. It returnsfalse
when using a youtube video url, and that is why the mediaelement.js player is not loaded in tinymce. Is his behavior intended ?