Monday, November 25, 2013

jQuery UI: Progressbar Finish Method

The jQuery UI progressbar widget typically gets marked as completed once the value reaches the maximum. For example, during an upload process, the maximum is set to the size of the file and the progressbar value is incremented with each chunk that is uploaded. This incremental update is continued till the value reaches the maximum. At this point, the complete event is triggered and no more updates take place - the progress is at 100%. This is the typical flow, but, it'd be nice to have a method to simply finish the progressbar update sequence. For example, maybe your application has some other means of notifying the UI that the process has completed.

To mark a progress bar as finished, and subsequently triggering the complete event, we just need to set the progressbar value to the maximum. Which means that we first need to read the maximum, determine if the value is already at the maximum, and if not, update the maximum. A lot of work for such a simple task. Let's abstract this behind a new progressbar method called finish(). Here's an example implementation. We have a progressbar and a button. Clicking the button causes the progressbar to finish by calling our new method. The button text is updated in response to the complete event.




The code to implement extend the progressbar widget is so small that it's worth looking at in its entirety.

$.widget( "app.progressbar", $.ui.progressbar, {
        
    finish: function() {
            
        var value = this.value(),
            max = this.options.max;
            
        if ( value !== max ) {
            this.value( max );    
        }
            
    }
        
});

This is an API extension of the progressbar widget. That is, finish is exposed in the same way as all other public methods — .progressbar( "finish" ). The value and max variables hold the current value and the max option, respectively. If we're not already at the maximum, set the value to the maximum, triggering the complete event. Note that this check for equality makes the method idempotent — only the first invocation will change the state of the widget.

$( "#progressbar" ).progressbar({
    max: 500,
    value: 250,
    complete: function( e, ui ) {
        $( "button" ).button( "option", "label", "Done!" );    
    }
})
        
$( "button" ).button().on( "click", function( e ) {
    $( "#progressbar" ).progressbar( "finish" );
})

Here is where we create our progressbar and button widgets. When the button is clicked, we call the finish() method. You can click the button as many times as you want — the complete event will only fire once.