Timeline control
by Nick Karnik
HTML
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css">
<div id="player" class="player unselectable">
<div id="play" class="play"> <i id="btnPlayIcon" class="fa fa-youtube-play fa-3x"></i>
</div>
<div id="slow" class="slow"> <i id="btnSlowIcon" class="fa fa-backward fa-2x"></i>
</div>
<div id="slider" class="slider">
<div id="track" class="track">
<div id="trackCompleted" class="trackCompleted"></div>
<div id="handle" class="handle">
<div id="runtimeInfo" class="runtimeInfo">
</div>
</div>
</div>
</div>
<div id="fast" class="fast"> <i id="btnFastIcon" class="fa fa-forward fa-2x"></i>
</div>
</div>
CSS
.runtimeInfo{
width:100px;
//background-color:lightgray;
//border: #4d8bb8 2px dashed;
//border: #21374c 2px dashed;
//background: #21374c;
text-align:center;
bottom: 35px;
left:-45px;
position: absolute;
border-radius:30px;
}
.slow {
left: 50px;
height: 20px;
color: lightgray;
text-align: center;
padding: 8px;
width: 40px;
position:absolute;
}
.slow:hover {
color: #ffffff;
cursor: pointer;
}
.fast {
right:0;
height: 20px;
color: lightgray;
text-align: center;
padding: 8px;
width: 40px;
position:absolute;
}
.fast:hover {
color: #ffffff;
cursor: pointer;
}
.play {
left: 8px;
height: 20px;
color: lightgray;
text-align: center;
width: 40px;
position:absolute;
z-index:1;
}
.play:hover {
color: #ffffff;
cursor: pointer;
}
.trackCompleted {
border-top-left-radius:13px;
border-bottom-left-radius:13px;
background-color: #4d8bb8;
left: 0;
position:absolute;
height: 20px;
}
.handle {
position: absolute;
float:left;
top: -4px;
height: 30px;
left: 0;
width:10px;
background-color: #21374c;
border-radius: 3px;
border: 1px dotted lightgray;
-webkit-transition: all 0s linear 0s;
-moz-transition: all 0s linear 0s;
-o-transition: all 0s linear 0s;
-ms-transition: all 0s linear 0s;
transition: all 0s linear 0s;
}
.handle:active {
-webkit-transition: none;
-moz-transition: none;
-o-transition: none;
-ms-transition: none;
transition: none;
cursor:e-resize;
border: solid 1px lightgray;
z-index: 1;
}
.handle:hover {
cursor:e-resize;
}
.player {
background-color: rgb(33, 55, 76);
position:absolute;
bottom:50%;
left:0;
right:0;
height: 45px;
}
.slider {
position: absolute;
background: #21374c;
border-radius: 13px;
height: 20px;
width: calc(100% - 160px);
padding: 3px;
...
JavaScript
var selected = false;
var playing = false;
var speedInTicks = 1;
var speedInMilliseconds = 1000;
var offset = 106;
//8px for padding on left button
trackCompleted.style.width = handle.getClientRects()[0].left + 8 - track.getClientRects()[0].left + "px";
play.addEventListener('click', function (e) {
if (!playing) {
playing = true;
btnPlayIcon.classList.remove('fa-youtube-play');
btnPlayIcon.classList.add('fa-pause');
handleTick();
} else {
playing = false;
btnPlayIcon.classList.remove('fa-pause');
btnPlayIcon.classList.add('fa-youtube-play');
}
});
track.addEventListener('mousedown', function (e) {
moveHandle(e);
playing = false;
selected = true;
});
handle.addEventListener('mousedown', function (e) {
selected = true;
playing = false;
});
var moveHandle = function (e) {
var location = e.clientX - offset;
if (location >= 0 && location <= track.clientWidth) {
handle.style.left = location + "px";
trackCompleted.style.width = location + "px";
}
};
var handleMouseup = function (e) {
selected = false;
// playing = true;
};
var handleMouseMove = function (e) {
if (selected) {
moveHandle(e);
}
};
document.addEventListener('mouseup', handleMouseup);
handle.addEventListener('mouseup', handleMouseup);
slider.addEventListener('mouseup', handleMouseup);
track.addEventListener('mouseup', handleMouseup);
handle.addEventListener('mousemove', handleMouseMove);
track.addEventListener('mousemove', handleMouseMove);
slider.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mousemove', handleMouseMove);
function handleTick() {
if (!selected && playing) {
playing = true;
if (handle.style.left == typeof (undefined) || handle.style.left === "") {
handle.style.left = trackCompleted.style.width;
}
var left = parseInt(handle.style.left, 10);
handle.style.left...