Skip to content

Instantly share code, notes, and snippets.

@brasofilo
Created May 22, 2013 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save brasofilo/5630542 to your computer and use it in GitHub Desktop.
Save brasofilo/5630542 to your computer and use it in GitHub Desktop.
Responsive audio player WordPress plugin based on http://osvaldas.info/audio-player-responsive-and-touch-friendly
/*
PLAYER
*/
.site-title {display:none;}
.audioplayer
{
height: 2.5em; /* 40 */
color: #fff;
text-shadow: 1px 1px 0 #000;
border: 1px solid #222;
position: relative;
z-index: 1;
background: #333;
background: -webkit-gradient( linear, left top, left bottom, from( #444 ), to( #222 ) );
background: -webkit-linear-gradient( top, #444, #222 );
background: -moz-linear-gradient( top, #444, #222 );
background: -ms-radial-gradient( top, #444, #222 );
background: -o-linear-gradient( top, #444, #222 );
background: linear-gradient( top, #444, #222 );
-webkit-box-shadow: inset 0 1px 0 rgba( 255, 255, 255, .15 ), 0 0 1.25em rgba( 0, 0, 0, .5 ); /* 20 */
-moz-box-shadow: inset 0 1px 0 rgba( 255, 255, 255, .15 ), 0 0 1.25em rgba( 0, 0, 0, .5 ); /* 20 */
box-shadow: inset 0 1px 0 rgba( 255, 255, 255, .15 ), 0 0 1.25em rgba( 0, 0, 0, .5 ); /* 20 */
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
.audioplayer-mini
{
width: 2.5em; /* 40 */
margin: 0 auto;
}
.audioplayer-mini audio
{
display: none;
}
.audioplayer > div
{
position: absolute;
}
.audioplayer-playpause
{
width: 2.5em; /* 40 */
height: 100%;
text-align: left;
text-indent: -9999px;
cursor: pointer;
z-index: 2;
top: 0;
left: 0;
}
.audioplayer:not(.audioplayer-mini) .audioplayer-playpause
{
border-right: 1px solid #555;
border-right-color: rgba( 255, 255, 255, .1 );
}
.audioplayer-mini .audioplayer-playpause
{
width: 100%;
}
.audioplayer-playpause:hover,
.audioplayer-playpause:focus
{
background-color: #222;
}
.audioplayer-playpause a
{
display: block;
}
.audioplayer:not(.audioplayer-playing) .audioplayer-playpause a
{
width: 0;
height: 0;
border: 0.5em solid transparent; /* 8 */
border-right: none;
border-left-color: #fff;
content: '';
position: absolute;
top: 50%;
left: 50%;
margin: -0.5em 0 0 -0.25em; /* 8 4 */
}
.audioplayer-playing .audioplayer-playpause a
{
width: 0.75em; /* 12 */
height: 0.75em; /* 12 */
position: absolute;
top: 50%;
left: 50%;
margin: -0.375em 0 0 -0.375em; /* 6 */
}
.audioplayer-playing .audioplayer-playpause a:before,
.audioplayer-playing .audioplayer-playpause a:after
{
width: 40%;
height: 100%;
background-color: #fff;
content: '';
position: absolute;
top: 0;
}
.audioplayer-playing .audioplayer-playpause a:before
{
left: 0;
}
.audioplayer-playing .audioplayer-playpause a:after
{
right: 0;
}
.audioplayer-time
{
width: 4.375em; /* 70 */
height: 100%;
line-height: 2.375em; /* 38 */
text-align: center;
z-index: 2;
top: 0;
}
.audioplayer-time-current
{
border-left: 1px solid #111;
border-left-color: rgba( 0, 0, 0, .25 );
left: 2.5em; /* 40 */
}
.audioplayer-time-duration
{
border-right: 1px solid #555;
border-right-color: rgba( 255, 255, 255, .1 );
right: 2.5em; /* 40 */
}
.audioplayer-novolume .audioplayer-time-duration
{
border-right: 0;
right: 0;
}
.audioplayer-bar
{
height: 0.875em; /* 14 */
background-color: #222;
cursor: pointer;
z-index: 1;
top: 50%;
right: 6.875em; /* 110 */
left: 6.875em; /* 110 */
margin-top: -0.438em; /* 7 */
}
.audioplayer-novolume .audioplayer-bar
{
right: 4.375em; /* 70 */
}
.audioplayer-bar div
{
width: 0;
height: 100%;
position: absolute;
left: 0;
top: 0;
}
.audioplayer-bar-loaded
{
background-color: #333;
z-index: 1;
}
.audioplayer-bar-played
{
background: #007fd1;
background: -webkit-gradient( linear, left top, right top, from( #007fd1 ), to( #c600ff ) );
background: -webkit-linear-gradient( left, #007fd1, #c600ff );
background: -moz-linear-gradient( left, #007fd1, #c600ff );
background: -ms-radial-gradient( left, #007fd1, #c600ff );
background: -o-linear-gradient( left, #007fd1, #c600ff );
background: linear-gradient( left, #007fd1, #c600ff );
z-index: 2;
}
.audioplayer-volume
{
width: 2.5em; /* 40 */
height: 100%;
border-left: 1px solid #111;
border-left-color: rgba( 0, 0, 0, .25 );
text-align: left;
text-indent: -9999px;
cursor: pointer;
z-index: 2;
top: 0;
right: 0;
}
.audioplayer-volume:hover,
.audioplayer-volume:focus
{
background-color: #222;
}
.audioplayer-volume-button
{
width: 100%;
height: 100%;
}
.audioplayer-volume-button a
{
width: 0.313em; /* 5 */
height: 0.375em; /* 6 */
background-color: #fff;
display: block;
position: relative;
z-index: 1;
top: 40%;
left: 35%;
}
.audioplayer-volume-button a:before,
.audioplayer-volume-button a:after
{
content: '';
position: absolute;
}
.audioplayer-volume-button a:before
{
width: 0;
height: 0;
border: 0.5em solid transparent; /* 8 */
border-left: none;
border-right-color: #fff;
z-index: 2;
top: 50%;
right: -0.25em;
margin-top: -0.5em; /* 8 */
}
.audioplayer:not(.audioplayer-mute) .audioplayer-volume-button a:after
{
/* "volume" icon by Nicolas Gallagher, http://nicolasgallagher.com/pure-css-gui-icons */
width: 0.313em; /* 5 */
height: 0.313em; /* 5 */
border: 0.25em double #fff; /* 4 */
border-width: 0.25em 0.25em 0 0; /* 4 */
left: 0.563em; /* 9 */
top: -0.063em; /* 1 */
-webkit-border-radius: 0 0.938em 0 0; /* 15 */
-moz-border-radius: 0 0.938em 0 0; /* 15 */
border-radius: 0 0.938em 0 0; /* 15 */
-webkit-transform: rotate( 45deg );
-moz-transform: rotate( 45deg );
-ms-transform: rotate( 45deg );
-o-transform: rotate( 45deg );
transform: rotate( 45deg );
}
.audioplayer-volume-adjust
{
height: 6.25em; /* 100 */
cursor: default;
position: absolute;
left: 0;
right: -1px;
top: -9999px;
background: #222;
background: -webkit-gradient( linear, left top, left bottom, from( #444 ), to( #222 ) );
background: -webkit-linear-gradient( top, #444, #222 );
background: -moz-linear-gradient( top, #444, #222 );
background: -ms-radial-gradient( top, #444, #222 );
background: -o-linear-gradient( top, #444, #222 );
background: linear-gradient( top, #444, #222 );
-webkit-border-top-left-radius: 2px;
-webkit-border-top-right-radius: 2px;
-moz-border-radius-topleft: 2px;
-moz-border-radius-topright: 2px;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.audioplayer-volume:not(:hover) .audioplayer-volume-adjust
{
opacity: 0;
}
.audioplayer-volume:hover .audioplayer-volume-adjust
{
top: auto;
bottom: 100%;
}
.audioplayer-volume-adjust > div
{
width: 40%;
height: 80%;
background-color: #222;
cursor: pointer;
position: relative;
z-index: 1;
margin: 30% auto 0;
}
.audioplayer-volume-adjust div div
{
width: 100%;
height: 100%;
position: absolute;
bottom: 0;
left: 0;
background: #007fd1;
background: -webkit-gradient( linear, left bottom, left top, from( #007fd1 ), to( #c600ff ) );
background: -webkit-linear-gradient( bottom, #007fd1, #c600ff );
background: -moz-linear-gradient( bottom, #007fd1, #c600ff );
background: -ms-radial-gradient( bottom, #007fd1, #c600ff );
background: -o-linear-gradient( bottom, #007fd1, #c600ff );
background: linear-gradient( bottom, #007fd1, #c600ff );
}
.audioplayer-novolume .audioplayer-volume
{
display: none;
}
.audioplayer-play,
.audioplayer-pause,
.audioplayer-volume a
{
-webkit-filter: drop-shadow( 1px 1px 0 #000 );
-moz-filter: drop-shadow( 1px 1px 0 #000 );
-ms-filter: drop-shadow( 1px 1px 0 #000 );
-o-filter: drop-shadow( 1px 1px 0 #000 );
filter: drop-shadow( 1px 1px 0 #000 );
}
.audioplayer-bar,
.audioplayer-bar div,
.audioplayer-volume-adjust div
{
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.audioplayer-bar,
.audioplayer-volume-adjust > div
{
-webkit-box-shadow: -1px -1px 0 rgba( 0, 0, 0, .5 ), 1px 1px 0 rgba( 255, 255, 255, .1 );
-moz-box-shadow: -1px -1px 0 rgba( 0, 0, 0, .5 ), 1px 1px 0 rgba( 255, 255, 255, .1 );
box-shadow: -1px -1px 0 rgba( 0, 0, 0, .5 ), 1px 1px 0 rgba( 255, 255, 255, .1 );
}
.audioplayer-volume-adjust div div,
.audioplayer-bar-played
{
-webkit-box-shadow: inset 0 0 5px rgba( 255, 255, 255, .5 );
-moz-box-shadow: inset 0 0 5px rgba( 255, 255, 255, .5 );
box-shadow: inset 0 0 5px rgba( 255, 255, 255, .5 );
}
.audioplayer-volume-adjust
{
-webkit-box-shadow: -2px -2px 2px rgba( 0, 0, 0, .15 ), 2px -2px 2px rgba( 0, 0, 0, .15 );
-moz-box-shadow: -2px -2px 2px rgba( 0, 0, 0, .15 ), 2px -2px 2px rgba( 0, 0, 0, .15 );
box-shadow: -2px -2px 2px rgba( 0, 0, 0, .15 ), 2px -2px 2px rgba( 0, 0, 0, .15 );
}
.audioplayer *,
.audioplayer *:before,
.audioplayer *:after
{
-webkit-transition: color .25s ease, background-color .25s ease, opacity .5s ease;
-moz-transition: color .25s ease, background-color .25s ease, opacity .5s ease;
-ms-transition: color .25s ease, background-color .25s ease, opacity .5s ease;
-o-transition: color .25s ease, background-color .25s ease, opacity .5s ease;
transition: color .25s ease, background-color .25s ease, opacity .5s ease;
}
/* responsiveness */
@media only screen and ( max-width: 32.5em ) /* 520 */
{
body
{
-webkit-box-shadow: inset 0 0 9.375em rgba( 0, 0, 0, .5 ); /* 150 */
-moz-box-shadow: inset 0 0 9.375em rgba( 0, 0, 0, 5 ); /* 150 */
box-shadow: inset 0 0 9.375em rgba( 0, 0, 0, .5 ); /* 150 */
}
#wrapper
{
width: 100%;
height: auto;
position: static;
padding: 1.25em; /* 20 */
margin: 0;
}
}
/*
VIEWPORT BUG FIX
iOS viewport scaling bug fix, by @mathias, @cheeaun and @jdalton
*/
(function(doc){var addEvent='addEventListener',type='gesturestart',qsa='querySelectorAll',scales=[1,1],meta=qsa in doc?doc[qsa]('meta[name=viewport]'):[];function fix(){meta.content='width=device-width,minimum-scale='+scales[0]+',maximum-scale='+scales[1];doc.removeEventListener(type,fix,true);}if((meta=meta[meta.length-1])&&addEvent in doc){fix();scales=[.25,1.6];doc[addEvent](type,fix,true);}}(document));
/*
AUTHOR: Osvaldas Valutis, www.osvaldas.info
*/
jQuery(document).ready(function($) {
var isTouch = 'ontouchstart' in window,
eStart = isTouch ? 'touchstart' : 'mousedown',
eMove = isTouch ? 'touchmove' : 'mousemove',
eEnd = isTouch ? 'touchend' : 'mouseup',
eCancel = isTouch ? 'touchcancel' : 'mouseup',
secondsToTime = function( secs )
{
var hours = Math.floor( secs / 3600 ), minutes = Math.floor( secs % 3600 / 60 ), seconds = Math.ceil( secs % 3600 % 60 );
return ( hours == 0 ? '' : hours > 0 && hours.toString().length < 2 ? '0'+hours+':' : hours+':' ) + ( minutes.toString().length < 2 ? '0'+minutes : minutes ) + ':' + ( seconds.toString().length < 2 ? '0'+seconds : seconds );
},
canPlayType = function( file )
{
var audioElement = document.createElement( 'audio' );
return !!( audioElement.canPlayType && audioElement.canPlayType( 'audio/' + file.split( '.' ).pop().toLowerCase() + ';' ).replace( /no/, '' ) );
};
$.fn.audioPlayer = function( params )
{
var params = $.extend( { classPrefix: 'audioplayer', strPlay: 'Play', strPause: 'Pause', strVolume: 'Volume' }, params ),
cssClass = {},
cssClassSub =
{
playPause: 'playpause',
playing: 'playing',
time: 'time',
timeCurrent: 'time-current',
timeDuration: 'time-duration',
bar: 'bar',
barLoaded: 'bar-loaded',
barPlayed: 'bar-played',
volume: 'volume',
volumeButton: 'volume-button',
volumeAdjust: 'volume-adjust',
noVolume: 'novolume',
mute: 'mute',
mini: 'mini'
};
for( var subName in cssClassSub )
cssClass[ subName ] = params.classPrefix + '-' + cssClassSub[ subName ];
this.each( function()
{
if( $( this ).prop( 'tagName' ).toLowerCase() != 'audio' )
return false;
var $this = $( this ),
audioFile = $this.attr( 'src' ),
isAutoPlay = $this.get( 0 ).getAttribute( 'autoplay' ), isAutoPlay = isAutoPlay === '' || isAutoPlay === 'autoplay' ? true : false,
isLoop = $this.get( 0 ).getAttribute( 'loop' ), isLoop = isLoop === '' || isLoop === 'loop' ? true : false,
isSupport = false;
if( typeof audioFile === 'undefined' )
{
$this.find( 'source' ).each( function()
{
audioFile = $( this ).attr( 'src' );
if( typeof audioFile !== 'undefined' && canPlayType( audioFile ) )
{
isSupport = true;
return false;
}
});
}
else if( canPlayType( audioFile ) ) isSupport = true;
var thePlayer = $( '<div class="' + params.classPrefix + '">' + ( isSupport ? $( '<div>' ).append( $this.eq( 0 ).clone() ).html() : '<embed src="' + audioFile + '" width="0" height="0" volume="100" autostart="' + isAutoPlay.toString() +'" loop="' + isLoop.toString() + '" />' ) + '<div class="' + cssClass.playPause + '" title="' + params.strPlay + '"><a href="#">' + params.strPlay + '</a></div></div>' ),
theAudio = isSupport ? thePlayer.find( 'audio' ) : thePlayer.find( 'embed' ), theAudio = theAudio.get( 0 ),
playPause = thePlayer.find( '.' + cssClass.playPause );
if( isSupport )
{
thePlayer.find( 'audio' ).css( { 'width': 0, 'height': 0, 'visibility': 'hidden' } );
thePlayer.append( '<div class="' + cssClass.time + ' ' + cssClass.timeCurrent + '"></div><div class="' + cssClass.bar + '"><div class="' + cssClass.barLoaded + '"></div><div class="' + cssClass.barPlayed + '"></div></div><div class="' + cssClass.time + ' ' + cssClass.timeDuration + '"></div><div class="' + cssClass.volume + '"><div class="' + cssClass.volumeButton + '" title="' + params.strVolume + '"><a href="#">' + params.strVolume + '</a></div><div class="' + cssClass.volumeAdjust + '"><div><div></div></div></div></div>' );
var theBar = thePlayer.find( '.' + cssClass.bar ),
barPlayed = thePlayer.find( '.' + cssClass.barPlayed ),
barLoaded = thePlayer.find( '.' + cssClass.barLoaded ),
timeCurrent = thePlayer.find( '.' + cssClass.timeCurrent ),
timeDuration = thePlayer.find( '.' + cssClass.timeDuration ),
volumeButton = thePlayer.find( '.' + cssClass.volumeButton ),
volumeAdjuster = thePlayer.find( '.' + cssClass.volumeAdjust + ' > div' ),
volumeDefault = 0,
adjustCurrentTime = function( e )
{
theRealEvent = isTouch ? e.originalEvent.touches[ 0 ] : e;
theAudio.currentTime = Math.round( ( theAudio.duration * ( theRealEvent.pageX - theBar.offset().left ) ) / theBar.width() );
},
adjustVolume = function( e )
{
theRealEvent = isTouch ? e.originalEvent.touches[ 0 ] : e;
theAudio.volume = Math.abs( ( theRealEvent.pageY - ( volumeAdjuster.offset().top + volumeAdjuster.height() ) ) / volumeAdjuster.height() );
},
updateLoadBar = function() {
setTimeout( function() {
barLoaded.width( ( theAudio.buffered.end( 0 ) / theAudio.duration ) * 100 + '%' );
if( theAudio.buffered.end( 0 ) < theAudio.duration )
updateLoadBar( updateLoadBar );
}, 100 );
};
var volumeTestDefault = theAudio.volume, volumeTestValue = theAudio.volume = 0.111;
if( Math.round( theAudio.volume * 1000 ) / 1000 == volumeTestValue ) theAudio.volume = volumeTestDefault;
else thePlayer.addClass( cssClass.noVolume );
timeDuration.html( '&hellip;' );
timeCurrent.text( secondsToTime( 0 ) );
theAudio.addEventListener( 'loadedmetadata', function()
{
updateLoadBar();
});
theAudio.addEventListener( 'loadeddata', function()
{
timeDuration.text( secondsToTime( theAudio.duration ) );
volumeAdjuster.find( 'div' ).height( theAudio.volume * 100 + '%' );
volumeDefault = theAudio.volume;
});
theAudio.addEventListener( 'timeupdate', function()
{
timeCurrent.text( secondsToTime( theAudio.currentTime ) );
barPlayed.width( ( theAudio.currentTime / theAudio.duration ) * 100 + '%' );
});
theAudio.addEventListener( 'volumechange', function()
{
volumeAdjuster.find( 'div' ).height( theAudio.volume * 100 + '%' );
if( theAudio.volume > 0 && thePlayer.hasClass( cssClass.mute ) ) thePlayer.removeClass( cssClass.mute );
if( theAudio.volume <= 0 && !thePlayer.hasClass( cssClass.mute ) ) thePlayer.addClass( cssClass.mute );
});
theAudio.addEventListener( 'ended', function()
{
thePlayer.removeClass( cssClass.playing );
});
theBar.on( eStart, function( e )
{
adjustCurrentTime( e );
theBar.on( eMove, function( e ) { adjustCurrentTime( e ); } );
})
.on( eCancel, function()
{
theBar.unbind( eMove );
});
volumeButton.on( 'click', function()
{
if( thePlayer.hasClass( cssClass.mute ) )
{
thePlayer.removeClass( cssClass.mute );
theAudio.volume = volumeDefault;
}
else
{
thePlayer.addClass( cssClass.mute );
volumeDefault = theAudio.volume;
theAudio.volume = 0;
}
return false;
});
volumeAdjuster.on( eStart, function( e )
{
adjustVolume( e );
volumeAdjuster.on( eMove, function( e ) { adjustVolume( e ); } );
})
.on( eCancel, function()
{
volumeAdjuster.unbind( eMove );
});
}
else thePlayer.addClass( cssClass.mini );
if( isAutoPlay ) thePlayer.addClass( cssClass.playing );
theAudio.addEventListener( 'play', function()
{
$( 'audio[data-playing=true]' ).each(function() {
this.pause();
});
$( theAudio ).attr( 'data-playing', 'true' );
playPause.attr( 'title', params.strPause ).find( 'a' ).html( params.strPause );
thePlayer.addClass( cssClass.playing );
});
theAudio.addEventListener( 'pause', function()
{
$( theAudio ).removeAttr( 'data-playing' );
playPause.attr( 'title', params.strPlay ).find( 'a' ).html( params.strPlay );
thePlayer.removeClass( cssClass.playing );
});
thePlayer.find( '.' + cssClass.playPause ).on( 'click', function()
{
theAudio.paused ? theAudio.play() : theAudio.pause();
return false;
});
$this.replaceWith( thePlayer );
});
return this;
};
$( 'audio' ).audioPlayer();
});
<?php
/*
Plugin Name: Responsive Audio Player
Description: WordPress plugin for http://osvaldas.info/audio-player-responsive-and-touch-friendly.
Usage: [resp-player width="50%" mp3="http://example.com/file.mp3"]
Version: 0.1
Author: Rodolfo Buaiz
Author URI: http://www.rodbuaiz.com
*/
add_shortcode( 'resp-player', 'b5f_responsive_audio_shortcode' );
add_action( 'wp_enqueue_scripts', 'b5f_enqueue_shortcode_scripts' );
add_action( 'wp_default_scripts', 'ds_enqueue_jquery_in_footer' );
function b5f_responsive_audio_shortcode($atts)
{
$width = isset( $atts['width'] ) ? " style='width:{$atts['width']}'" : '';
$mp3 = isset( $atts['mp3'] ) ? '<source src="' . $atts['mp3'] .'" />' : '';
$ogg = isset( $atts['ogg'] ) ? "<source src='{$atts['ogg']}' />" : '';
$wav = isset( $atts['wav'] ) ? "<source src='{$atts['wav']}' />" : '';
?>
<div<?php echo $width; ?>>
<audio controls preload="auto">
<?php echo $mp3; ?>
<?php echo $ogg; ?>
<?php echo $wav; ?>
This text displays if the audio tag isn't supported.
</audio>
</div>
<?php
}
function b5f_enqueue_shortcode_scripts()
{
if( b5f_post_has_shortcode( 'resp-player' ) )
{
wp_enqueue_style( 'resp-player-css', plugins_url( 'audio-player.css', __FILE__) );
wp_enqueue_script( 'resp-player-js', plugins_url( 'audio-player.js', __FILE__), array('jquery'), false, true );
}
}
/**
* Description: Prints jQuery in footer on front-end.
* Author: Dominik Schilling
* Author URI: http://wpgrafie.de/
*/
function ds_enqueue_jquery_in_footer( &$scripts ) {
if ( ! is_admin() )
$scripts->add_data( 'jquery', 'group', 1 );
}
function b5f_post_has_shortcode($shortcode = '')
{
$post_to_check = get_post(get_the_ID());
$found = false;
if (!$shortcode)
return $found;
if ( stripos($post_to_check->post_content, '[' . $shortcode) !== false )
$found = true;
return $found;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment