I mentioned in yesterday's blog posting on the Sortable plugin that I was taking a closer look at jQuery UI and how I could integrate it with ColdFusion. I've taken a closer look at another of the widgets and thought I'd share my findings. (Also please note a personal request at the end.)

The jQuery Progress Bar is pretty much what you would expect it to be. A bar. That shows progress. Yes, not rocket science, I know. Here is an example using the Swanky Purse theme (still my favorite theme):

The code behind this is ridiculously simple:

<html>

<head> <link type="text/css" rel="stylesheet" href="theme/ui.all.css" /> <script src="jquery-1.3.1.js"></script> <script src="jquery-ui-personalized-1.6rc6.js"></script> <script> $(document).ready(function() { $("#progressbar").progressbar({value:69}) }); </script> </head>

<body>

<div id="progressbar"></div> </body> </html>

Like other widgets, I have to remember to include my CSS along with the JavaScript. Once I've done that, I simply tell the plugin to turn a particular ID into a progress bar. The code above uses a hard coded value of 69. Progress bars uses a value system based on a percentage from 0 to 100. You can see this in action here.

Obviously a static progress bar isn't too exciting, and when I was mentally preparing this blog post in my head this is the part where I was going to immediately jump into creating a dynamic progress bar. However - it occurred to me that a static bar isn't exactly useless either. Imagine a case where you want to mark the progress of something that takes place over a few days, or weeks. For example, a donation drive. You may get one donation per day. It would be kind of silly to build an auto-updating Ajax-driven progress bar for something that won't likely change for a web site visitor. At the same time, you don't want to have to build a new graphic as the donation drive goes on. A static progress bar would be a great - and simple - way to handle this. Consider:

<!--- Imagine a cfquery here to get total donation ---> <cfset donations = 99> <cfset perc = int(donations/399*100)>

<html>

<head> <link type="text/css" rel="stylesheet" href="theme/ui.all.css" /> <script src="jquery-1.3.1.js"></script> <script src="jquery-ui-personalized-1.6rc6.js"></script> <script> $(document).ready(function() { <cfoutput> $("##progressbar").progressbar({value:#perc#}) </cfoutput> }); </script> </head>

<body>

<h1>Buy Ray a PS3 Support Fund!</h1>

<div id="progressbar"></div> </body> </html>

This is pretty much the exact same code as above but now I have a bit of code to determine the current percentage. My JavaScript code makes use of this value and I added a label over the progress bar so it was a bit more obvious. You can see this in action here.

So what if you do want a dynamic progress bar? As you can imagine the docs go into detail about what events and methods you can use with the progress bar. Getting the current value is as easy as:

var currentValue = $("#pb").progressbar('option','value');

and setting then is:

$("#pb").progressbar('option','value',currentValue);

I quickly created a new demo that would let me increase and decrease the values:

<html>

<head> <link type="text/css" rel="stylesheet" href="theme/ui.all.css" /> <script src="jquery-1.3.1.js"></script> <script src="jquery-ui-personalized-1.6rc6.js"></script> <script>

function less() { var currentValue = $("#pb").progressbar('option','value'); currentValue--; if(currentValue >= 0) $("#pb").progressbar('option','value',currentValue); }

function more() { var currentValue = $("#pb").progressbar('option','value'); currentValue++; if(currentValue <= 100) $("#pb").progressbar('option','value',currentValue); }

$(document).ready(function() { $("#pb").progressbar({value:69}) $("#lessBtn").click(less); $("#moreBtn").click(more); }); </script> </head>

<body>

<div id="pb"></div> <input type="button" id="lessBtn" value="Less"> <input type="button" id="moreBtn" value="More">

</body> </html>

I've added two buttons, Less and More, each of which will run a simple function to either increase or decrease the progress bar value. I added a bit of logic to ensure I don't go below 0 or above 100. You can see this demo here.

Ok, so time to get sexy. A progress bar is really useful for monitoring a slow process. You can imagine something like image resizing. Shrinking a large directory of images could take a while and it would be nice to present a UI to the user so they can see the progress of the slow process. I designed a simple ColdFusion demo that will hopefully demonstrate how you could do this.

First, I added an Application.cfc just to enable Application variable support:

<cfcomponent output="false">

<cfset this.name = "jqpb">

<cffunction name="onApplicationStart" returnType="boolean" output="false"> <cfreturn true> </cffunction>

<cffunction name="onRequestStart" returnType="boolean" output="false"> <cfargument name="thePage" type="string" required="true">

<cfif structKeyExists(url, "reinit")> <cfset onApplicationStart()> </cfif>

<cfreturn true> </cffunction>

<cffunction name="onError" returnType="void" output="false"> <cfargument name="exception" required="true"> <cfargument name="eventname" type="string" required="true"> <cfdump var="#arguments#"><cfabort> </cffunction>

</cfcomponent>

Next, I created my CFM page that would handle running the slow process. I decides to use a simple timer system:

<cfsetting enablecfoutputonly="true">

<!--- start a process that takes 60 seconds. ---> <cfif not structKeyExists(application, "process")> <cfset application.process = now()> </cfif>

<!--- app.process is a timestamp, determine how much of the 60 seconds we have finished. if 60 or more, report 100 and kill the process ---> <cfset diff = dateDiff("s",application.process, now())>

<cfif diff gte 60> <cfset structDelete(application, "process")> <cfoutput>100</cfoutput> <cfelse> <cfset perc = diff/60*100> <cfoutput>#int(perc)#</cfoutput> </cfif>

This code will look for an Application variable named process. If it doesn't exist, it will be created and set to the current time.

I then check the difference in seconds from the variable. If less then 60, I output the the percentage value of the time passed. If greater than 60, I output 100 and remove the variable. (Note - this code would need to have locking added to be properly single threaded!) I tested this by hitting it in my browser and reloading. I watched the value go slowly from 0 to 100 and then back again. Once I was sure it worked ok I then moved on to the front end.

I began by adding a button beneath my progress bar:

<div id="pb"></div> <input type="button" id="startBtn" value="Start">

I then modified my document.ready to initialize the progress bar to 0 and listen for the button's click event:

$(document).ready(function() { $("#pb").progressbar({value:0}) $("#startBtn").click(startProcess); });

startProcess will now handle creating a timer:

var timer;

function startProcess() { $("#startBtn").attr("disabled","disabled") $("#startBtn").attr("value","Working...") checkProcess() timer = setInterval(checkProcess,1000) }

I do a few things here besides just starting the timer. I disable and change the value of the start button. I run checkProcess immediately, and then set an interval for the function.

checkProcess handles doing an Ajax call to my CFM above:

function checkProcess() { $.get('process.cfm',{},function (data,textStatus) { $("#pb").progressbar('option','value',$.trim(data)) if(data == 100) { clearInterval(timer) $("#startBtn").removeAttr("disabled") $("#startBtn").attr("value","Start") } }) }

I run a simple get and then examine the result. I set the progress bar to the number returned, and if the value was 100, I handle killing the timer and resetting the button.

You can see this in action here. Note - the file you run is a CFM file but I don't actually use ColdFusion in the view at all. It should have been an HTML file. (I hope I can be forgiven for defaulting all my files to ColdFusion files out of habit!)

p.s. I've been doing a lot of jQuery posts lately. I hope my readers are enjoying them. I'm trying my best to tie each post to something ColdFusion related as well. If anyone has feedback on this, let me know via email. I'm hoping these articles are helpful to those new to jQuery, or perhaps looking for ways to integrate jQuery more with ColdFusion.