Simple jQuery-CSS progress bar

by mmarcon

HTML

<div class="progress">
    <section class="progress-message"></section>
    <section class="progress-val">
        <span class="min"></span>
        <span class="val"><p></p></span>
        <span class="max"></span>
    </section>
</div>

CSS

body {
    background-color: #4badde;
    font-family: helvetica, arial, sans-serif;
    font-weight: 100;
}

.progress {
    width: 300px;
    height: 200px;
    margin: 10px auto;
    background-color: #333;
    border: 1px solid #111;
    color: #fff;
}

.progress section {
    width: 260px;
    margin: auto;
}

.progress .progress-message {
    margin-top: 30px;
}

.progress-val {
    position: relative;
}

.progress-val .min {
    position: absolute;
    top: 0;
    left: 0;
}

.progress-val .max {
    position: absolute;
    top: 0;
    right: 0;
}

.progress .val {
    display: block;
    width: 258px;
    height: 30px;
    border: 1px solid #fff;
    border-radius: 2px;
    position: relative;
    line-height: 30px;
    font-size: 12px;
    text-align: center;
    color: #ff8c00;
    top: 20px;
    overflow: hidden;
}

.progress .val p {
    position: relative;
    z-index: 1000;
}

.visual-progress {
    position: absolute;
    top: 0;
    left: 0;
    height: 30px;
    background-color: #fff;
    display: block;
    z-index: 999;
}

JavaScript

$(function(){
    var progress = {
        message: $('.progress .progress-message'),
        min: $('.progress .progress-val .min'),
        max: $('.progress .progress-val .max'),
        val: $('.progress .progress-val .val'),
        
        setMin: function (min, show) {
            if(show) this.min.text (min);
            this.min.data('val', min);
        },
        
        setMax: function (max, show) {
            if(show) this.max.text (max);
            this.max.data('val', max);
        },
        
        setVal: function (val) {
            this.setUndetermined (false);
            var rVal = val - this.min.data('val');
            var rMax = this.max.data('val') - this.min.data('val');
            var p = rVal * 100 / rMax;
            progress.val.data ('val', val);
            progress.val.data ('percentage', p);
            progress.val.children('p').text (p + '%');
            
            var $p = $('<span/>').addClass('visual-progress');
            progress.val.append($p);
            $p.width($p.parent().width() * p / 100);
        },
        
        setUndetermined: function (undermined) {
            if (undermined) {
                progress.val.data ('val', 'undetermined');
                progress.val.children('p').text (null);
                var $p = $('<span/>').addClass('visual-progress');
                progress.val.append($p);
                $p.width (10).fadeTo(0, 0.2);
                var animate = function() {
                    $p.css({
                        left: -10
                    });
                    $p.animate({
                        left: $p.parent().width()
                    }, 2000, null, animate);
                };
                animate();
            }
            else {
                $('span.visual-progress').stop().remove();
            }
        }
    };
    
    progress.message.text('Loading...');
    
    progress.setMin(0);
    progress.setMax(100);
    //progress.setUndetermined...