DeComponeur player

by PhilQ

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<audio id="audio" preload="auto">
	<source src="http://www.archive.org/download/bolero_69/Bolero.mp3" type="audio/mpeg">
	Your browser does not support the audio element.
</audio>

<ul id="audiocontrols">
	<li class="play"><a href="#">
		<i class="fa fa-play" aria-hidden="true"></i>
		<i class="fa fa-pause" aria-hidden="true"></i>
	</a></li>
	<li class="track">
		<div class="buffered"></div>
		<div class="position"></div>
		<a href="#" class="seek"></a>
		<div class="time">00:00</div>
		<div class="duration">00:00</div>
	</li>
	<li class="volume on">
		<div class="level"></div>
		<a href="#" class="set">
			<i class="fa fa-volume-off" aria-hidden="true"></i>
			<i class="fa fa-volume-down" aria-hidden="true"></i>
			<i class="fa fa-volume-up" aria-hidden="true"></i>
		</a>
	</li>
</ul>

<ul id="playlist">
	<li class="active">
		<a href="http://www.archive.org/download/bolero_69/Bolero.mp3">
			Ravel Bolero<i>2:55</i>
		</a>
	</li>
	<li>
		<a href="http://www.archive.org/download/MoonlightSonata_755/Beethoven-MoonlightSonata.mp3">
			Moonlight Sonata - Beethoven<i>2:55</i>
		</a>
	</li>
	<li>
		<a href="http://www.archive.org/download/CanonInD_261/CanoninD.mp3">
			Canon in D Pachabel<i>2:55</i>
		</a>
	</li>
	<li>
		<a href="http://www.archive.org/download/PatrikbkarlChamberSymph/PatrikbkarlChamberSymph_vbr_mp3.zip">
			patrikbkarl chamber symph<i>2:55</i>
		</a>
	</li>
</ul>

TODO:
1a) (JS & CSS) Volume bar
1b) (JS) arrow-keys (seek, volume)
2) (JS) allow-acces-init-before-playing
3) (PHP) check if stream-script still works

SCSS

*,:before,:after{margin:0;padding:0;box-sizing:border-box;}
body {background-color:#201e1f;font-family:sans-serif;padding:50px;}


audio {
	visibility: hidden;
	opacity: 0;
	z-index: -1;
	width: 0px;
	height: 0px;
	overflow: hidden;
	pointer-events: none;
	display: inline-block;
}

$color: #666;
$color-light: lighten($color, 10%);

#audiocontrols, #playlist {
	position: relative;
	display: block;
	max-width: 478px;
	width: 100%;
	clear: both;
	float: left;
    margin-top: 10px;
	background-color: $color;
	list-style: none;
	a {
		outline: none;
	}
}
#audiocontrols {
	height: 32px;
	box-shadow:
		inset 0px -1px 0px 0px rgba(0,0,0, 0.15),
		inset 0px 1px 0px 0px rgba(255,255,255, 0.2),
		inset 0px -20px 26px -10px rgba(0,0,0, 0.3);

	.play {
		position: absolute;
		display: inline-block;
		top: 0px;
		left: 5px;
		width: 32px;
		height: 32px;
		// border: 1px solid rgba(255,255,255, 0.1);
		
		> a {
			// color: darken($color, 20%);
			color: lighten($color, 30%);
			// text-shadow: 0px 1px 0px rgba(255,255,255, 0.1);

			> i {
				position: absolute;
				display: inline-block;
				top: 50%;
				left: 50%;
				transform: translate(-50%, -50%);
			}
			&:hover, &:focus {
				> i {
					color: lighten($color, 50%);
					// text-shadow: 0px 1px 2px rgba(0,0,0, 0.6);
					text-shadow: 0px 1px 5px rgba(0,0,0, 1);
				}
			}
			> i.fa-pause {display: none;}
		}
		&.playing > a > i.fa-play {display: none;}
		&.playing > a > i.fa-pause {display: inline-block;}
	}

	.track {
		position: absolute;
		top: 0px;
		left: 47px;
		right: (47px + 80px);
		display: inline-block;
		height: 32px;
		// border: 1px solid rgba(255,255,255, 0.1);
		
		.time, .duration {
			position: absolute;
			top: 50%;
			left: 100%;
			margin-left: 53px;
			width: 47px;
			text-align: left;
			font-size: 11px;
			color: lighten($color, 10%);
			margin-top: -5px;
		}
		.time {
			margin-left: 0px;
			width: 47px;
			text-align: right;
			color: lighten($color, 30%);
		}
		.buffered, .position...

JavaScript

var player_time;
function updateTime(p) {
	pos = ((p.currentTime / p.duration) * 100);
	$('#audiocontrols .position').css('width', pos + '%');
	$('#audiocontrols .seek').css('left', pos + '%');
	t = p.currentTime;
	tm = Math.floor(t/60);
	th = Math.floor(tm/60);
	tm = (th>0)? tm - (th*60): tm;
	th = (th>0)? th + ':': '';
	ts = ('00' + Math.round(t - (tm*60))).substr(-2);
	tm = ('00' + tm).substr(-2) + ':';
	$('#audiocontrols .time').html(th + tm + ts);
};

$(document).ready(function () {
	init();
	function init(){
		var current = 0;
		var audio = $('#audio');
		var playlist = $('#playlist');
		var tracks = playlist.find('li a');
		var len = tracks.length - 1;
		audio[0].volume = .7; //.35;
		
		playlist.on('click','a', function(e){
			e.preventDefault();
			link = $(this);
			current = link.parent().index();
			run(link, audio[0]);
		});
		
		audio[0].addEventListener('volumechange',function(e){
			// alert('Vol=' + this.volume);
		});
		audio[0].addEventListener('loadedmetadata',function(e){
			$('#audiocontrols .time').html('--:--');
			t = this.duration;
			tm = Math.floor(t/60);
			th = Math.floor(tm/60);
			tm = (th>0)? tm - (th*60): tm;
			th = (th>0)? th + ':': '';
			ts = ('00' + Math.round(t - (tm*60))).substr(-2);
			tm = ('00' + tm).substr(-2) + ':';
			$('#audiocontrols .duration').html(th + tm + ts);
		});
		audio[0].addEventListener('playing',function(e){
			clearInterval(player_time);
			$('#audiocontrols .play').addClass('playing');
			updateTime(audio[0]);
			player_time = setInterval(function(){
				updateTime(audio[0]);
			}, 1000);
		});
		audio[0].addEventListener('pause',function(e){
			clearInterval(player_time);
			$('#audiocontrols .play').removeClass('playing');
		});
		audio[0].addEventListener('ended',function(e){
			clearInterval(player_time);
			$('#audiocontrols .time').html('--:--');
			// $('#audiocontrols .duration').html('--:--');
			current++;
			if(current == len){
				current = 0;
				link =...