Mediaelement loads video player in an audio tag

2019-08-13 22:03发布

问题:

I'm using a javascript code to load links to mp3 using medialement.js

The configuration is as follows:

HTML

<a class="audio-player" href="some.mp3">This mp3 is cool</a>

Javascript:

var audioDiv = document.getElementsByClassName("audio-player");
$(audioDiv).each(function(index) {
  if ($(this).className != 'mediaplayer-processed') {
    var playlist = $(this).attr('href');
    playlist = playlist.replace("%20", " ");
    sourceType = playlist.split('.').pop().toLowerCase();
    if (sourceType == 'mp3') {
      sourceType = 'mpeg';
    }
    audioTag = '<audio class="audio-player">'
    audioTag = audioTag + '<source type="audio/' + sourceType + '" src="' + playlist + '" />';
    audioTag = audioTag + '</audio>';
    $(this).outerHTML=audioTag;
    config_me = {
      // enables Flash and Silverlight to resize to content size
      enableAutosize: true,
      // the order of controls you want on the control bar (and other plugins below)
      features: ['playpause','volume'],
      // Hide controls when playing and mouse is not over the video
      alwaysShowControls: true,
    };
    // I need to set the video height and width because it is displayed as video
    config_me.videoHeight = 30;
    config_me.videoWidth = 60;
    config_me.audioWidth = 60;
    config_me.audioHeight = 30;
    config_me.loop = false;

    $(this).addClass('mediaplayer-processed').mediaelementplayer(config_me);
  }
});

Now what I would expect/want is a minimalistic audio player, but what I get is a full video player and mediaelement loads with the class "mejs-video" instead "mejs-audio".

I tried forcing the type in config_me, but it is still loaded as a video.

Am I missing something? I'm using mediaelement 2.15.2.

回答1:

There are some subtle details you should consider in your code

FIRST, this :

$(this).outerHTML = audioTag;

... will never work (see jsfiddle) because $(this) refers to a jQuery object, not to a document object.

Because of that, the <audio> tag never replaces the <a> tag, so

$(this).addClass('mediaplayer-processed').mediaelementplayer(config_me);

... is actually binding mediaelementplayer() to your current <a> tag, and MEJS configures it as video by default because there is nothing in there that tells it's an audio.

In that case, you should do :

this.outerHTML = audioTag;

See jsfiddle


SECOND, after you finally replace the a tag with the video tag, this

$(this).addClass('mediaplayer-processed').mediaelementplayer(config_me);

... still doesn't bind mediaelementplayer() to the audio tag because $(this) refers to an element that doesn't exist anymore (the <a> tag) so in that case you should do :

$(".audio-player").addClass('mediaplayer-processed').mediaelementplayer(config_me);

... because the video tag now also shares the audio-player class.

Please notice however, that if you initialize mediaelementplayer() inside the .each() method, only the first element will be correctly initialized because it will be the only one audio tag with that class. The rest of the elements with class audio-player are still <a> tags during the first loop (and you will be back to your original problem)

As a workaround, you have two options :

  1. Leave the mediaelementplayer() method inside the .each() method BUT add different classes to your new video tags like :

    audioTag = '<audio class="audio-player'+index+'">'
    

    ... then, initialize them like :

    $(".audio-player"+index+"").addClass('mediaplayer-processed').mediaelementplayer(config_me);
    
  2. Leave your code the way it is but just move the mediaelementplayer() method after the .each() method like :

    $(audioDiv).each(function (index) { 
        if() {... }
    });
    $(".audio-player").addClass('mediaplayer-processed').mediaelementplayer(config_me);
    

NOTICE either of the configurations above will convert ALL a tags into audio tags on page load.

Here is your complete working code with the second option

jQuery(document).ready(function ($) {
    var audioDiv = document.getElementsByClassName("audio-player");
    $(audioDiv).each(function (index) {
        if ($(this).className != 'mediaplayer-processed') {
            var playlist = $(this).attr('href');
            playlist = playlist.replace("%20", " ");
            sourceType = playlist.split('.').pop().toLowerCase();
            console.log(sourceType);
            if (sourceType == 'mp3') {
                sourceType = 'mpeg';
            }
            audioTag = '<audio class="audio-player">'
            audioTag = audioTag + '<source type="audio/' + sourceType + '" src="' + playlist + '" />';
            audioTag = audioTag + '</audio>';
            // $(this).outerHTML = audioTag;
            this.outerHTML = audioTag;
            config_me = {
                enableAutosize: true,
                features: ['playpause', 'volume'],
                alwaysShowControls: true,
            };
            //config_me.videoHeight = 30;
            //config_me.videoWidth = 60;
            config_me.audioWidth = 120;
            config_me.audioHeight = 30;
            config_me.loop = false;
        }
    }); // each
    $(".audio-player").addClass('mediaplayer-processed').mediaelementplayer(config_me);
}); // ready

See jsfiddle

Notice I set a higher width in config_me.audioWidth = 120; because you will need some extra room for the volume handler.


THIRD, if your idea is that audio elements should be shown after clicking the corresponding link (and not on page load as in the example above), then you have to bind a click event using the .on() method inside the .each() method.

Notice that in this case, it's advisable to add a different class to each audio tag (as in option 1 above) so we can initialize them individually after each click so

jQuery(document).ready(function ($) {
    var audioDiv = document.getElementsByClassName("audio-player");
    $(audioDiv).each(function (index) {
        $(this).on("click", function (e) {
            if ($(this).className != 'mediaplayer-processed') {
                var playlist = this.href; // $(this).attr('href');
                playlist = playlist.replace("%20", " ");
                sourceType = playlist.split('.').pop().toLowerCase();
                console.log(sourceType);
                if (sourceType == 'mp3') {
                    sourceType = 'mpeg';
                }
                audioTag = '<audio class="audio-player'+index+'">'
                audioTag = audioTag + '<source type="audio/' + sourceType + '" src="' + playlist + '" />';
                audioTag = audioTag + '</audio>';
                // $(this).outerHTML = audioTag;
                this.outerHTML = audioTag;
                config_me = {
                    enableAutosize: true,
                    features: ['playpause', 'volume'],
                    alwaysShowControls: true,
                };
                //config_me.videoHeight = 30;
                //config_me.videoWidth = 60;
                config_me.audioWidth = 120;
                config_me.audioHeight = 30;
                config_me.loop = false;
                $(".audio-player"+index+"").addClass('mediaplayer-processed').mediaelementplayer(config_me);
            }
            return false;
       }); // on
    }); // each
}); // ready

See jsfiddle