whatever123
whatever123

Reputation: 179

Progress bar with slide ability

I am new to JavaScript/CSS (basically the whole world of web dev) and I am really struggling to create the following widget. I created a picture of what I want to make to make it more clear.

enter image description here

The Play/Pause and Stop button are ready. Loop checkbox is no problem. But the progress bar is painful. The two markers are supposed to mark the point from where the file would start playing and where it would stop. The progress bar is also supposed to be click-able, so if I want to access a certain point in time, then its possible.

What I tried so far

jQuery UI slider: For a sliding progress bar and use that draggable slider to access a certain point in audio file. Works fine. But no markers and looks really ugly. Don't how to change it.

<progress> tag: not very flexible. Marker? Clicking?

<div> tag: there seems to be no way to get the point where I clicked.

So, what do you guys recommend? How should I proceed?

Upvotes: 6

Views: 10810

Answers (2)

Jeff Noel
Jeff Noel

Reputation: 7618

Canvas Alternative

You might want to use a canvas and draw your own progress bar element within it.

Here are some canvas progress bar tutorials:


Doing it with <progress>

To access the clicked position within a DOMElement, you can proceed with the click event's properties: clientX and clientY (MDN Source), like so:

HTML

<div class="marker" id="StartMarker">^</div>
<div class="marker" id="StopMarker">^</div>
<progress id="progress" value="0" min="0" max="100">0%</progress>
<form id="choice">
    <button id="marker1">Beginning marker</button>
    <button id="marker2">Ending marker</button>
    <input type="hidden" id="markerValue" value="0" />
</form>

JavaScript (not optimized)

document.getElementById('progress').onclick = function (event, element) {
    /* Math.floor((event.offsetX / this.offsetWidth) * 100) */
    var newProgress = event.offsetX;

    document.getElementById('choice').style.display = "block";
    document.getElementById('markerValue').setAttribute('value', newProgress);

    document.getElementById('marker1').onclick = function (event) {
        event.preventDefault();

        var newProgress = document.getElementById('markerValue').value;
        var progressBar = document.getElementById('progress');
        var startMarker = document.getElementById('StartMarker');
        var stopMarker = document.getElementById('StopMarker');

        var marker = startMarker;
        marker.style.display = "block";

        startMarker.style.display = "block";
        startMarker.offsetTop = (progressBar.offsetTop + progressBar.offsetHeight + 2) + "px";
        startMarker.style.left = newProgress + "px";

    };

    document.getElementById('marker2').onclick = function (event) {
        event.preventDefault();

        var newProgress = document.getElementById('markerValue').value;
        var progressBar = document.getElementById('progress');
        var startMarker = document.getElementById('StartMarker');
        var stopMarker = document.getElementById('StopMarker');


        stopMarker.style.display = "block";
        stopMarker.offsetTop = (progressBar.offsetTop + progressBar.offsetHeight + 2) + "px";
        stopMarker.style.left = newProgress + "px";
    };
};

CSS

.marker {
    position:absolute;
    top:24px;
    left:9px;
    display:none;
    z-index:8;
    font-weight:bold;
    text-align:center;
}
#StartMarker {
    color: #CF0;
}
#StopMarker {
    color:#F00;
}
#choice {
    display:none;
}
progress {
    display: inline-block;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    width: 300px;
    height: 20px;
    padding: 3px 3px 2px 3px;
    background: #333;
    background: -webkit-linear-gradient(#2d2d2d, #444);
    background: -moz-linear-gradient(#2d2d2d, #444);
    background: -o-linear-gradient(#2d2d2d, #444);
    background: linear-gradient(#2d2d2d, #444);
    border: 1px solid rgba(0, 0, 0, .5);
    border-radius: 15px;
    box-shadow: 0 1px 0 rgba(255, 255, 255, .2);
}

Live Demo

Upvotes: 5

Miiller
Miiller

Reputation: 1063

Using simple blocks for that is possible. Your layout would look like this (simplified):

HTML

<div class="progressbar">
    <div class="bar">
        <div class="progress" style="width: 30%;">
        </div>
    </div>
    <div class="markers">
        <div class="right" style="width: 70%;">
            <div class="marker">
            </div>
            <div class="left" style="width: 20%;">
                <div class="marker">
                </div>
            </div>
        </div>
    </div>
</div>

SCSS

.progressbar {
    width: 20em;
    background: grey;
    .bar {
        height: 2em;
        .progress {
            background: blue;
            height: 100%;
        }
    }
    .markers {
        height: 1em;
        background: white;
        .right {
            height: 100%;
            background: red;
            .marker {
                width: 1em;
                height: 100%;
                background: green;
                position: relative;
                float: right;
            }
            .left {
                background: white;
                height: 100%;
            }
        }
    }
}

The operations can be quite difficult

jQuery

$('.bar').click(function(e){
    $(this).find('.progress').css('width', (e.offsetX / this.offsetWidth)*100+'%');
});

will set the Progressbar properly on clicks.

For the markers though you will need mousedown, mousemove, mouseleave events, since you got 2 of them.

Example

http://jsfiddle.net/JXauW/

Upvotes: 2

Related Questions