Audio player, tweaks to suit

This commit is contained in:
Sam Potts 2015-02-15 12:17:16 +11:00
parent 63c1d04d72
commit 0f77a44472
7 changed files with 180 additions and 75 deletions

View File

@ -24,9 +24,9 @@
var defaults = {
debug: false,
seekInterval: 10,
volume: 5,
selectors: {
container: ".player",
videoContainer: ".player-video",
controls: ".player-controls",
buttons: {
play: "[data-player='play']",
@ -45,6 +45,7 @@
seekTime: ".player-seek-time"
},
classes: {
videoContainer: "player-video",
stopped: "stopped",
playing: "playing",
muted: "muted",
@ -170,6 +171,38 @@
return string.replace(new RegExp(find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"), "g"), replace);
}
// Wrap an element
function wrap(elements, wrapper) {
// Convert `elms` to an array, if necessary.
if (!elements.length) {
elements = [elements];
}
// Loops backwards to prevent having to clone the wrapper on the
// first element (see `child` below).
for (var i = elements.length - 1; i >= 0; i--) {
var child = (i > 0) ? wrapper.cloneNode(true) : wrapper;
var el = elements[i];
// Cache the current parent and sibling.
var parent = el.parentNode;
var sibling = el.nextSibling;
// Wrap the element (is automatically removed from its current
// parent).
child.appendChild(el);
// If the element had a sibling, insert the wrapper before
// the sibling to maintain the HTML structure; otherwise, just
// append it to the parent.
if (sibling) {
parent.insertBefore(child, sibling);
} else {
parent.appendChild(child);
}
}
}
// Get click position relative to parent
// http://www.kirupa.com/html5/getting_mouse_click_position.htm
function getClickPosition(e) {
@ -336,7 +369,6 @@
player.buttons.rewind = getElement(config.selectors.buttons.rewind);
player.buttons.forward = getElement(config.selectors.buttons.forward);
player.buttons.mute = getElement(config.selectors.buttons.mute);
player.buttons.volume = getElement(config.selectors.buttons.volume);
player.buttons.captions = getElement(config.selectors.buttons.captions);
player.buttons.fullscreen = getElement(config.selectors.buttons.fullscreen);
@ -345,6 +377,9 @@
player.progress.bar = getElement(config.selectors.progress);
player.progress.text = player.progress.bar.getElementsByTagName("span")[0];
// Volume
player.volume = getElement(config.selectors.buttons.volume);
// Timing
player.duration = getElement(config.selectors.duration);
player.seekTime = getElements(config.selectors.seekTime);
@ -376,13 +411,30 @@
play();
}
// Set volume
function setVolume() {
player.volume.value = config.volume;
player.media.volume = parseFloat(config.volume / 10);
checkMute();
}
// Check mute state
function checkMute() {
if(player.media.volume === 0 || player.media.muted) {
player.container.className += " " + config.classes.muted;
}
else {
player.container.className = player.container.className.replace(config.classes.muted, "");
}
}
// Setup media
function setupMedia() {
player.media = player.container.querySelectorAll("audio, video")[0];
// If there's no media, bail
if(!player.media) {
console.warn("No audio or video element found!");
console.error("No audio or video element found!");
return false;
}
@ -396,11 +448,24 @@
// Set type
player.type = (player.media.tagName.toLowerCase() == "video" ? "video" : "audio");
// Inject the player wrapper
if(player.type === "video") {
// Create the wrapper div
var wrapper = document.createElement("div");
wrapper.setAttribute("class", config.classes.videoContainer);
// Wrap the video in a container
wrap(player.media, wrapper);
// Cache the container
player.videoContainer = wrapper;
}
}
// Setup captions
function setupCaptions() {
if(player.type == "video") {
if(player.type === "video") {
// Inject the container
player.videoContainer.insertAdjacentHTML("afterbegin", "<div class='" + config.selectors.captions.replace(".", "") + "'></div>");
@ -583,7 +648,6 @@
// Listen for events
function listeners() {
// Fullscreen
player.buttons.fullscreen.addEventListener("click", function() {
if(!fullscreen.isFullScreen()) {
@ -595,17 +659,19 @@
}, false);
// Click video
player.videoContainer.addEventListener("click", function() {
if(player.media.paused) {
play();
}
else if(player.media.ended) {
restart();
}
else {
pause();
}
}, false);
if(player.type === "video") {
player.videoContainer.addEventListener("click", function() {
if(player.media.paused) {
play();
}
else if(player.media.ended) {
restart();
}
else {
pause();
}
}, false);
}
// Play
player.buttons.play.addEventListener("click", function() {
@ -633,7 +699,7 @@
player.media.currentTime = targetTime;
}
// Special handling for "manual" captions
if (!player.isTextTracks) {
if (!player.isTextTracks && player.type === "video") {
adjustManualCaptions(player);
}
}, false);
@ -649,26 +715,26 @@
player.media.currentTime = targetTime;
}
// Special handling for "manual" captions
if (!player.isTextTracks) {
if (!player.isTextTracks && player.type === "video") {
adjustManualCaptions(player);
}
}, false);
// Get the HTML5 range input element and append audio volume adjustment on change
player.buttons.volume.addEventListener("change", function() {
player.media.volume = parseFloat(this.value / 10);
player.volume.addEventListener("change", function() {
config.volume = this.value;
setVolume();
}, false);
// Mute
player.buttons.mute.addEventListener("click", function() {
if (player.media.muted === true) {
player.media.muted = false;
player.container.className = player.container.className.replace(config.classes.muted, "");
}
else {
player.media.muted = true;
player.container.className += " " + config.classes.muted;
}
checkMute();
}, false);
// Duration
@ -700,7 +766,7 @@
player.media.currentTime = player.pos * player.media.duration;
// Special handling for "manual" captions
if (!player.isTextTracks) {
if (!player.isTextTracks && player.type === "video") {
adjustManualCaptions(player);
}
});
@ -717,7 +783,9 @@
// Clear captions at end of video
player.media.addEventListener("ended", function() {
player.captionsContainer.innerHTML = "";
if(player.type === "video") {
player.captionsContainer.innerHTML = "";
}
player.container.className = player.container.className.replace(config.classes.playing, config.classes.stopped);
});
}
@ -732,8 +800,7 @@
}
function setupPlayer(element) {
player.container = element;
player.videoContainer = getElement(config.selectors.videoContainer);
player.container = element;
// Setup media
setupMedia();
@ -747,6 +814,9 @@
// Find the elements
findElements();
// Set volume
setVolume();
// Captions
setupCaptions();
@ -773,22 +843,25 @@
// Debug info
if(config.debug) {
console.log(config);
console.log("fullscreen support: " + fullscreen.supportsFullScreen);
console.log(fullscreen.supportsFullScreen ? "Fullscreen supported" : "No fullscreen supported");
console.log(player.browserName + " " + player.browserMajorVersion);
}
// If IE8, stop customization (use fallback)
// If IE9, stop customization (use native controls)
if (player.browserName === "IE" && (player.browserMajorVersion === 8 || player.browserMajorVersion === 9) ) {
console.warn("Browser not suppported.");
if(config.debug) {
console.error("Browser not suppported.");
}
return false;
}
// If smartphone or tablet, stop customization as video (and captions in latest devices) are handled natively
player.isSmartphoneOrTablet = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(navigator.userAgent);
if (player.isSmartphoneOrTablet) {
console.warn("Browser not suppported.");
if(config.debug) {
console.error("Browser not suppported.");
}
return false;
}
@ -801,25 +874,17 @@
}
// Get the container and video container
var elements = document.querySelectorAll(config.selectors.container);
for (var i = elements.length - 1; i >= 0; i--) {
setupPlayer(elements[i]);
var element = document.querySelector(config.selectors.container);
if(element === null) {
if(config.debug) {
console.error("Selector " + config.selectors.container + " not found!");
}
return false;
}
setupPlayer(element);
//now we execute callbacks registered to shout
executeHandlers("setup");
}
}(this.simpleMedia = this.simpleMedia || {}));
/*function InitPxVideo(options) {
"use strict";
// ***
// Captions
// ***
}*/

View File

@ -21,14 +21,7 @@
@progress-bg: @gray;
@progress-value-bg: @blue;
// BORDER-BOX ALL THE THINGS! (http://paulirish.com/2012/box-sizing-border-box-ftw/)
// -------------------------------
.player,
.player *,
.player *::after,
.player *::before {
box-sizing: border-box;
}
// Utility classes & mixins
// -------------------------------
@ -76,6 +69,14 @@
overflow: hidden; // For the controls
background: #000;
// BORDER-BOX ALL THE THINGS!
// http://paulirish.com/2012/box-sizing-border-box-ftw/
&,
*,
*::after,
*::before {
box-sizing: border-box;
}
// For video
&-video {
@ -309,7 +310,7 @@
}
}
/* fixing display for IE10+ */
// Fixing display for IE10+
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.video-controls .player-volume {
position: relative;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,23 +18,15 @@
</header>
<div class="player">
<div class="player-video">
<video width="640" height="360" poster="../media/poster_PayPal_Austin2.jpg" controls>
<!-- video files -->
<source src="https://www.paypalobjects.com/webstatic/mktg/videos/PayPal_AustinSMB_baseline.mp4" type="video/mp4" />
<source src="https://www.paypalobjects.com/webstatic/mktg/videos/PayPal_AustinSMB_baseline.webm" type="video/webm" />
<audio controls>
<!-- Audio files -->
<source src="../media/Covox_-_Switchblade_Squadron.mp3" type="audio/mp3">
<!-- text track file -->
<track kind="captions" label="English captions" src="../media/captions_PayPal_Austin_en.vtt" srclang="en" default />
<!-- fallback for browsers that don't support the video element -->
<div>
<a href="https://www.paypalobjects.com/webstatic/mktg/videos/PayPal_AustinSMB_baseline.mp4">
<img src="../media/poster_PayPal_Austin2.jpg" width="640" height="360" alt="download video" />
</a>
</div>
</video>
</div>
<!-- Fallback for browsers that don't support the <audio> element -->
<div>
<a href="../media/Covox_-_Switchblade_Squadron.mp3">Download it</a>
</div>
</video>
</div>
<!-- Load SVG defs -->

47
docs/video.html Normal file
View File

@ -0,0 +1,47 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Simple Media</title>
<meta name="description" content="Custom HTML5 video controls and WebVTT captions.">
<meta name="author" content="Sam Potts">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Styles -->
<link rel="stylesheet" href="../dist/css/simple-media.css">
<link rel="stylesheet" href="../dist/css/docs.css">
</head>
<body class="container">
<header>
<h1>Simple Media</h1>
<p>A simple HTML5 media player</p>
</header>
<div class="player">
<video poster="../media/poster_PayPal_Austin2.jpg" controls>
<!-- Video files -->
<source src="https://www.paypalobjects.com/webstatic/mktg/videos/PayPal_AustinSMB_baseline.mp4" type="video/mp4">
<source src="https://www.paypalobjects.com/webstatic/mktg/videos/PayPal_AustinSMB_baseline.webm" type="video/webm">
<!-- Text track file -->
<track kind="captions" label="English captions" src="../media/captions_PayPal_Austin_en.vtt" srclang="en" default>
<!-- Fallback for browsers that don't support the <video> element -->
<div>
<a href="https://www.paypalobjects.com/webstatic/mktg/videos/PayPal_AustinSMB_baseline.mp4">
<img src="../media/poster_PayPal_Austin2.jpg" width="640" height="360" alt="download video">
</a>
</div>
</video>
</div>
<!-- Load SVG defs -->
<script>(function(d,p){var a=new XMLHttpRequest(),b=d.body; a.open("GET",p,!0);a.send();a.onload=function(){var c=d.createElement("div");c.style.display="none";c.innerHTML=a.responseText;b.insertBefore(c,b.childNodes[0])}})(document,"../dist/svg/sprite.svg");</script>
<!-- Core player -->
<script src="../dist/js/simple-media.js"></script>
<!-- Docs setup -->
<script src="../dist/js/docs.js"></script>
</body>
</html>

Binary file not shown.