Search code examples
jqueryjquery-uiuser-interfaceprogress-barprogress

Segmented progressbar (jQuery UI)


I'm trying to divide the jQuery UI progressbar into segments.

Does anybody know how I would do this?

Example: (2 - Visual Design: 03 http://wiki.jqueryui.com/w/page/12138028/Progressbar)

(I'm currently using background-images, but that's not practical.)


Solution

  • Here is a prototype I was working on...

    CSS:

    div { margin:10px 10px 0px 10px; height:24px; }
    div.progressContainer { clear:both; display:block; }
    label { float:left; width:200px; display:block; }
    input { float:left; width:100px; text-align:center; display:inline; }
    input[type=button] { margin-right:1.5px; }
    

    HTML:

    <!-- Options -->
    <div> <!-- Maximum -->
        <label> Maximum ProgressBar Value </label>
        <input id="max" type="text" value="100" />
    </div>
    <div> <!-- Initial Value -->
        <label> Initial Value </label>
        <input id="val" type="text" value="43" />
    </div>
    <div> <!-- Width -->
        <label> ProgressBar Width </label>
        <input id="width" type="text" value="304" />
    </div>
    <div> <!-- Height -->
        <label> ProgressBar Height </label>
        <input id="height" type="text" value="30" />
    </div>
    <div> <!-- Multiply -->
        <label> Segmented ProgressBar </label>
        <input id="seg" type="text" value="4" />
    </div>
    <!-- Create ProgressBar by given options -->
    <div>
        <input type="button" value="Create" />
    </div>
    <!-- ProgressBar Container -->
    <div class="progressContainer"> </div>
    <!-- Action Buttons -->
    <div>
        <input type="button" value="Start" /> <input type="button" value="Stop" /> <input type="button" value="Reset" />
    </div>
    

    jQuery:

    var i; // Define a global counter
    var tmr; // Define timer
    
    // Create Function
    function create() {
        var max = parseInt($("input#max").val(),10),
            val = parseInt($("input#val").val(),10),
            seg = parseInt($("input#seg").val(),10),
            width = parseInt($("input#width").val(),10),
            height = parseInt($("input#height").val(),10);
        $(".progressContainer").empty().height(height).width(width);
        // Get size for each progressbar
        var size = max / seg;
        // Get width for each progressbar
        // -2 for left/right borders of progressbars
        // -1 for margin-right
        // = -3px each of their width to fit exact location
        width = (width / seg) - 3;
        for(i=0; i<seg; i++) {
            // Create segmented progressbars
            $(".progressContainer").append(
                '<div class="progress' + i + '"></div>');
            // Add their size
            $(".progress" + i).progressbar({
                max: size, value: 0
            }).css({
                margin: '0 1px 0 0',
                width: width,
                height: height,
                float:'left'
            });
        }
        // Get initial value
        var init = val;
        if (init < size) {
            // if smaller than size
            // than only 1 bar gonna get filled
            $(".progress0").progressbar({ value: init });
        } else if (init > size) {
            // else calgulate how many bars
            // gonna be effected
            var bars = Math.floor(init / size);
            for(i=0; i<bars; i++) {
                init = Math.abs(init - size);
                $(".progress" + i).progressbar({ value: size });
            }
            // fill the value left to the last bar
            $(".progress" + i).progressbar({ value: init });
        }
        // Now get the hell out of here!
    }
    
    function inc() {
        // Define required values
        var max = parseInt($("input#max").val(),10),
            seg = parseInt($("input#seg").val(),10),
            val = parseInt($("input#val").val(),10);
        // Get size for each progressbar
        var size = max / seg;
        // Get initial value
        var init = val;
        var next = val + 1;
        // If progress is at max then reset it
        if (init >= max) {
            init = 1;
            next = 1;
            for (i=0;i<seg;i++) {
                $(".progress" + i).progressbar({ value: 0 });
            }
        }
        if (init < size) {
            // if smaller than size
            // than only 1 bar gonna get filled
            $(".progress0").progressbar({ value: init });
        } else if (init > size) {
            // else calgulate how many bars
            // gonna be effected
            var bars = Math.floor(init / size);
            for(i=0; i<bars; i++) {
                init = Math.abs(init - size);
                $(".progress" + i).progressbar({ value: size });
            }
            // fill the value left to the last bar
            // +1 here is just for making bar look fullfilled
            $(".progress" + i).progressbar({ value: init + 1});
        }
        // Next value
        $("input#val").val(next);
        // Loop
        tmr = setTimeout(inc, 1000);
        // Now get the hell out of here!
    }
    
    // Start Function
    function start() {
        // Set's interval to timer and starts
        tmr = setTimeout(inc, 1000);
        // Now get the hell out of here!
    }
    
    // Stop Function
    function stop() {
        // Stops the timer
        clearTimeout(tmr);
        // Now get the hell out of here!
    }
    
    // Reset Function
    function reset() {
        var seg =  parseInt($("input#seg").val(),10);
        // For segmented bars
        $("input#val").val(0);
        // Get initial value
        for(i=0; i<seg; i++) {
            $(".progress" + i).progressbar({ value: 0 });
        }
        // Now get the hell out of here!
    }
    
    // Validate Function
    function validate(element) {
        var obj = $(element);
        if(!/[0-9]$/.test(obj.val())) {
            // Invalid
            obj.css('box-shadow', '0px 0px 8px #FAC3C3');
            if(!obj.next().hasClass('error'))
            { obj.after('<span class="error error-keyup-1">Please use numbers only</span>'); }
        } else {
            // Valid
            obj.css('box-shadow', '0px 0px 8px lightgreen');
            if(obj.next().hasClass('error'))
            { obj.next().remove(); }
        }
        // Now get the hell out of here!
    }
    
    // Document Ready
    $(document).ready(function(){
        // Validate Inputs
        $("input[type=text]").each(function() {
            $(this).keyup(function(){
                validate(this);
                $(this).focusout(function() {
                    $(this).css('box-shadow', '0px 0px 0px #ffffff');
                });
            });
        });
        // Action Buttons
        $("input[type=button]").each(function() {
            // alert($(this).val());
            $(this).click(function(){
                if ($(this).val() == "Create") { create(); }
                if ($(this).val() == "Start") { start(); }
                if ($(this).val() == "Stop") { stop(); }
                if ($(this).val() == "Reset") { reset(); }
            });
        });
        // Now get the hell out of here!
    });
    

    jsfiddle: http://jsfiddle.net/BerkerYuceer/QZMMx/