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...