Player JS error when big pipe is enabled

Created on 19 January 2024, 5 months ago

Steps to reproduce

  • Install mediaelement and big_pipe
  • Create a video media entity with a file upload (field type is not a factor)
  • Set the "MediaElement.js Video" display formatter
  • Create a new media entity, upload a video, and go to the entity view for the simple media entity itself.

Problem/Motivation

When big pipe is enabled all the video media elements appear to have been loaded correctly, but will not play. This is related to πŸ› Big Pipe calls attachBehaviors twice Closed: works as designed , but still an issue even with all proper uses of the once() library.

Currently the once selector is using:
$(once('mediaelement', '.mediaelementjs', context))

The target is essentially something like<video class="mediaelementjs"> (simplified of course). The actual mediaelement library then creates wrapper html around that original tag, and, copies the classes from it.

We then end up with something like:

<div id="mep_0" class="mejs__container mejs__container-keyboard-inactive mediaelementjs media-player--inline mejs__video" tabindex="0" role="application" aria-label="Video Player" style="min-width: 319px;">
  <div class="mejs__inner">
    <div class="mejs__mediaelement">
      <mediaelementwrapper id="mejs_someid">
        <video width="640" height="480" preload="none" data-media-id="1234" data-mejsembed="1234" class="mediaelementjs media-player--inline" data-once="mediaelement" id="id1234" src="any_source">

What's happening then is big pipe is re-executing the behaviors. The 'data-once' has been applied to the <video>, but it hasn't been applied to the new <div class="mejs_container">, and since that also has the class of mediaelementjs, it is selected again with once and the player is applied again with additional wrapper HTML.

Proposed resolution

We need to ensure our selector doesn't select any other element other than the original. Since the original elements are always <video> and <audio>, and the generated code will never be another html media element, the simplest solution would be to use:

once('mediaElementPlayerInit', 'audio.mediaelementjs,video.mediaelementjs', context)

The benefit of this approach is that it will make more sense alongside the following code which is to optionally use this player for all audio and video elements globally.

$(once('mediaElementPlayerInit', 'audio,video', context))

Related changes included

  • I've changed the once identifier to mediaElementPlayerInit which I think is a little descriptive.
  • I've changed the function call for the .each() methods to include the automatically provided arguments of (i, e), which are the index and element respectively. This makes the actual call to mediaelement not have to rely on this which is often a lot less error prone for future updates.
    $(e).mediaelementplayer(settings.mediaelement);
πŸ› Bug report
Status

Needs review

Version

2.0

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States asherry

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

Production build 0.69.0 2024