Skip to content

Commit

Permalink
Revised for 1.1.1 release
Browse files Browse the repository at this point in the history
Many fixes in guard clauses, fallbacks for native HTML & non me-js environments (not playlist as it has no native analogue) & comments.

This is not a commercial packaged product, but is meant for others to put-in-place patterns I like, and learn about them.
  • Loading branch information
Lewiscowles1986 committed Nov 9, 2019
1 parent 9657e39 commit 9531275
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 30 deletions.
94 changes: 68 additions & 26 deletions index.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?php
/**
* Plugin Name: Media Playback Speed
* Description: Appends playback buttons to the Media Player. Updated original by Daron Spence.
* Description: Appends playback buttons to the Audio Player, Video Player & PLaylist shortcodes. Based on original by Daron Spence.
* Author: LewisCowles
* Version: 1.0.7
* Version: 1.1.1
*/

add_action( 'wp_footer', function(){
Expand Down Expand Up @@ -32,7 +32,9 @@
<?php endif; ?>
</script>
<script type="text/javascript">
// contain all JS effects of this plugin so we don't break sites
(function() {
// window.load is unfortunately the best handler to attach to for allowing media-element-js to initialize
window.addEventListener("load", function() {
var buttons = document.createRange().createContextualFragment(
document.querySelector("#playback-buttons-template").innerHTML
Expand All @@ -41,40 +43,80 @@

els.forEach(function(elem, i) {
var mediaTag = elem.querySelector('audio,video');

// buttons for me-js element
[].slice.call(
buttons.querySelectorAll('.playback-rate-button')
).forEach(function(elem) {
elem.setAttribute('aria-controls', mediaTag.id );
})
});

// parent for controls
var controls = elem.querySelector('.mejs-controls');
if(controls) {
var container =controls.querySelector('.mejs-duration-container');
container.parentNode.insertBefore(buttons.cloneNode(true), container.nextSibling);

mediaTag.addEventListener('loadedmetadata', function(e) {
var playlist = e.target.closest('.wp-playlist');
if(playlist) {
var activeSpeed = playlist.querySelector('.mejs-container .playback-rate-button.mejs-active'),
rate = activeSpeed.dataset.value;
e.target.setPlaybackRate(rate);
}
});
var container = controls.querySelector('.mejs-duration-container'),
hasSpeedControls = controls.querySelector('.playback-rate-button');

// Guard to ensure that this only affects as-yet unaffected elements
if (!hasSpeedControls) {
// insertAfter container
container.parentNode.insertBefore(buttons.cloneNode(true), container.nextSibling);

// when media is loaded persist the playback speed currently selected
mediaTag.addEventListener('loadedmetadata', function(e) {
var playlist = e.target.closest('.wp-playlist');
if(playlist) {
var activeSpeed = playlist.querySelector('.mejs-container .playback-rate-button.mejs-active'),
rate = activeSpeed.dataset.value;

// Guard against failing matchers. The DOM must be fulfilled, but this also means this part maybe doesn't need media-element-js
if(!rate) { return; }

// This is actually the magic. It's basically a more complex document.querySelector('video, audio').setPlaybackRate
e.target.setPlaybackRate(rate);
}
});
}
}
});
document.body.addEventListener('click', function(e) {
if(!e.target || !e.target.classList.contains('playback-rate-button')) { return; }
});

var btnEl = e.target,
mediaTag = document.querySelector(`#${e.target.getAttribute('aria-controls')}`),
rate = e.target.dataset.value;
mediaTag.setPlaybackRate(rate);
// AJAX / SPA supporting click bind handler
// Uses data attribute and aria attribute as well as class-names from media-element-js & this plugin
// because this binds to body it should always be available in a valid HTML page
document.body.addEventListener('click', function(e) {
// Because we're bound to body, we need to guard and only act on HTML elements with the right class
if(!e.target || !e.target.classList.contains('playback-rate-button')) { return; }

[].slice.call(
mediaTag.closest('.mejs-container').querySelectorAll('.playback-rate-button')
).map(function(elem) {
elem.classList.remove('mejs-active');
});
e.target.classList.add('mejs-active');
// We set aria attributes informing which DOMElement to control
var mediaTag = document.querySelector(`#${e.target.getAttribute('aria-controls')}`),
rate = e.target.dataset.value;

// Guard against failing matchers. The DOM must be fulfilled, but this also means this part maybe doesn't need media-element-js
if(!mediaTag || !rate) { return; }

// This is actually the magic. It's basically a more complex document.querySelector('video, audio').setPlaybackRate
mediaTag.setPlaybackRate(rate);

var mediaPlaybackContainer = mediaTag.closest('.mejs-container');

// This allows use outside of WordPress for this
if(!mediaPlaybackContainer) { mediaPlaybackContainer = document.body; }

// Clear all active playback rate buttons for this element of the active class
[].slice.call(
mediaPlaybackContainer.querySelectorAll('.playback-rate-button')
).map(function(elem) {
elem.classList.remove('mejs-active', 'active-playback-rate');
});

// Set the clicked element, or the matching to active rate to be active
[].slice.call(
mediaPlaybackContainer.querySelectorAll('.playback-rate-button')
).forEach(function(elem) {
if(rate && elem.dataset.value == rate) {
elem.classList.add('mejs-active', 'active-playback-rate');
}
});
});
})();
Expand Down
25 changes: 21 additions & 4 deletions readme.txt
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
=== Media Playback Speed ===
Contributors: LewisCowles,daronspence
Tags: frontend,media,streaming,aria,mediaelementjs,html5,video,audio,playback,speed,cd2,lewiscowles
Tags: frontend,media,streaming,aria,mediaelementjs,html5,video,audio,playback,speed,cd2,lewiscowles,codesign2,shortcode,playlist
Requires at least: 4.0
Tested up to: 5.2.2
Tested up to: 5.2.4
Requires PHP: 5.6
Stable tag: 1.0.7
Stable tag: 1.1.1
License: GPL-3.0
License URI: https://www.gnu.org/licenses/gpl-3.0.html

Add speed controls to audio and video hosted from your WordPress blog.

== Description ==
This short handy plugin will add playback buttons to your audio and video elements added via the built-in wordpress shortcodes for media using mediaelement.js. Each set of buttons is configured for it's corresponding element on the page, so you can adjust the speed of multiple files independantly.
This short, handy plugin will add playback buttons to your audio, video & playlist elements added via the built-in WordPress shortcodes for media using mediaelement.js.

Each set of buttons is configured for it's corresponding element on the page, so you can adjust the speed of multiple files independently.

There is currently no persistence implemented in this plugin. It just scratches an itch to be able to broadly adjust media playback speeds using the HTML api.

Expand All @@ -29,6 +31,18 @@ Two hooks are provided within this plugin.

`.playback-rate-button.mejs-active` CSS-selector allows you to style the active speed (per-player)

#### Troubleshooting

This works with the traditional `audio`, `video` and `playlist` shortcodes so long as WordPress uses the JavaScript player.

With the latest 1.1.1 release this also works for HTML5 audio and video too, however you will need to implement your own controls which have the `playback-rate-button` class and follow the patterns of this.

HTML5 raw controls do not have a playlist the author is aware of, and they use global state, so playback rate is per-page.

There is currently no history as part of this plugin, however a sister plugin could be authored and hooks added to it to store playback rate.

Please ensure that you have no broken javascript, or wrap all functions in `(function() { // do things })()` blocks to ensure nothing interferes with this plugin. This plugin does this so that it should not interfere with your site, even in browsers and pages which do not support this plugin.

#### Feedback

Please feel free to [suggest](https://github.com/CODESIGN2/media-playback-speed/issues) improvements, report conflicts, and/or make suggestions for integration hooks etc.
Expand All @@ -37,6 +51,9 @@ Please feel free to [suggest](https://github.com/CODESIGN2/media-playback-speed/
Download and extract the zip file or clone this repo to your WordPress plugins directory. Alternatively use the plugin directory to find and install this plugin.

== Changelog ==
= 1.1.1 =
* minor rewrite adding comments and building on the Vanilla JS 1.0.7 works

= 1.0.7 =
* guard to prevent errors

Expand Down

0 comments on commit 9531275

Please sign in to comment.