Posted in jQuery, ColdFusion | Posted on 07-20-2009 | 6,689 views
I haven't played much with ColdFusion 9's new Ajax UI tags, mainly because I'm kind of a jQuery UI fan boy now, but this morning I took a look at cfProgressBar. It's a nice little utility and has some interesting uses. Here are a few examples to help you learn the tag. (And hopefully avoid some of the documentation issues I ran into!)
First, let's look at an incredibly simple progress bar - one that has absolutely no tie to a real process.
2
3<head>
4<script>
5function init() {
6 ColdFusion.ProgressBar.start("mycfb")
7}
8</script>
9</head>
10
11<body>
12<h2>Processing your stuff...</h2>
13
14<cfprogressbar name="mycfb" duration="5000" interval="300" width="300" />
15
16<cfset ajaxOnLoad("init")>
17
18</body>
19</html>
Right off the bat, let me point some documentation bugs that may snare you. First, the cfprogressbar tag must have an end tag. That's kind of silly and I'm sure it will be corrected for the final release.
Secondly, both the width and interval attributes are marked as optional with defaults. As far as I can see, this is not the case. Width for me defaulted to 100%, and when I didn't supply an interval, the progress bar never did anything.
Moving on - the last thing to note is that a progress bar will not start running until you tell it to. In this case, I have a 'static' progress bar that uses a duration attribute. This progress bar will simply update it's status of 5000 ms, or 5 seconds. I start the progress bar using ColdFusion.ProgrsssBar.start(name), and, well, that's it.
You can view a demo of this here: http://cf9.coldfusionjedi.com/cfprogressbar/test.cfm
A static progress bar may not make much sense, but, I do think folks might have a use for it. You may have a slow process that has no direct API to check it's status. If you can roughly estimate how long the process normally takes, then this type of progress bar could at least give your user a reasonable idea of its progress. That being said, I think most folks will want to tie a progress bar to a real status. Let's look at an example of that now.
2
3<html>
4
5<head>
6<script>
7function init() {
8 ColdFusion.ProgressBar.start("mycfb")
9}
10</script>
11</head>
12
13<body>
14<h2>Processing your stuff...</h2>
15
16<cfprogressbar name="mycfb" bind="cfc:process.getStatus()" interval="600" width="300" />
17
18<cfset ajaxOnLoad("init")>
19
20</body>
21</html>
This example is much like the other, but note I've removed the duration and replaced it with a bind to a CFC. (Binds to JavaScript functions are also allowed.) My template initializes a session variable, cfpbtest, to 0. This is then used within my CFC:
2
3remote struct function getStatus() {
4 var result = {};
5
6 if(not structKeyExists(session, "cfpbtest")) session.cfpbtest = 0;
7 session.cfpbtest+=0.1;
8 if(session.cfpbtest > 1) session.cfpbtest = 1;
9 result.status = session.cfpbtest;
10
11 if(result.status == 1) result.message = "Woot! Done.";
12 if(result.status < 0.8) result.message = "Getting closer...";
13 if(result.status < 0.6) result.message = "More than halfway done...";
14 if(result.status < 0.4) result.message = "Still working, ways to go...";
15 if(result.status < 0.2) result.message = "Just begun...";
16
17 return result;
18
19}
20
21}
The API for progress bar bindings is pretty simple. The CFC method (or JavaScript function) does not take an attribute. It must return a structure with two keys, status and message. Status must be a number between 0 and 1. Message can be whatever you want, or blank even. WARNING: If you return a number higher than 1, the progress bar will correctly display it (i.e., it doesn't draw the progress past the end), but it will continue to peg your server. Notice my little check there to see if the value is over 1? I did that because I noticed floating point errors and an infinite loop of network calls. I've already logged a bug for this. Oh, and by the way, notice the interval value? If you set that too low, and you have an error in your CFC, you will get an infinite number of JavaScript alerts. I filed a bug report on that as well.
You can view this demo here: http://cf9.coldfusionjedi.com/cfprogressbar/test2.cfm
Here is another example that demonstrates the onComplete functionality. In this example, I've specified that the progress bar should hide itself when done:
2
3<html>
4
5<head>
6<script>
7function init() {
8 ColdFusion.ProgressBar.start("mycfb")
9}
10
11function hideme() {
12 ColdFusion.ProgressBar.hide("mycfb")
13}
14</script>
15</head>
16
17<body>
18<h2>Processing your stuff...</h2>
19
20<cfprogressbar name="mycfb" bind="cfc:process.getStatus()" interval="600" width="300" oncomplete="hideme" />
21
22<cfset ajaxOnLoad("init")>
23
24</body>
25</html>
The hideme function simply uses the hide function to make the progress bar disappear. You can view this demo here: http://cf9.coldfusionjedi.com/cfprogressbar/test3.cfm
Ok, so obviously this can be used to monitor the progress of some long running process. But you can also use it to provide feedback of a more manual process. Check out this example:
2
3<head>
4<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
5<script>
6
7function init() {
8 ColdFusion.ProgressBar.updateStatus('mycfb', 0, 'Form Status')
9}
10
11$(document).ready(function() {
12
13
14 $("input").change(function() {
15 var complete = 0
16 if($("#name").val() != '') complete+=0.25
17 if($("#age").val() != '') complete+=0.25
18 if($("#email").val() != '') complete+=0.25
19 if($("#cheese").val() != '') complete+=0.25
20 if(complete == 1) {
21 msg = 'Form Complete!'
22 $("#save").attr("disabled",false)
23 } else msg = 'Form Status'
24
25 ColdFusion.ProgressBar.updateStatus('mycfb',complete,msg)
26 })
27})
28</script>
29</head>
30
31<body>
32
33<cfprogressbar name="mycfb" width="300" />
34
35<p>
36<form>
37 Name: <input type="text" name="name" id="name"><br/>
38 Age: <input type="text" name="age" id="age"><br/>
39 Email: <input type="text" name="email" id="email"><br/>
40 Favorite Cheese: <input type="text" name="cheese" id="cheese"><br/>
41 <input type="submit" name="Save" id="save" disabled="true">
42</form>
43</p>
44
45</body>
46</html>
47
48<cfset ajaxOnLoad("init")>
I've created a simple form with 4 fields in it. I use jQuery to bind to all the inputs on the page, specifically their change event handler. Whenever you change the values of one of the form fields, I check all 4 fields and create a 'completed' value that represents how much of the form you have done. If you have all four done, I update the status and re-enable the submit button. You can view this demo here: http://cf9.coldfusionjedi.com/cfprogressbar/test4.cfm I think it's interesting as it provides the user feedback on how far they are in the process of finishing the form. It's overkill for just 4 fields, but you get the idea.


Yes please! ;]
How 'bout a demo?
I tested it out locally swapping the .blur event for the .change event and that corrects the issue.
$("input").blur(function() {
var complete = 0
if($("#name").val() != '') complete+=0.25
if($("#age").val() != '') complete+=0.25
if($("#email").val() != '') complete+=0.25
if($("#cheese").val() != '') complete+=0.25
if(complete == 1) {
msg = 'Form Complete!'
$("#save").attr("disabled",false)
} else{
msg = 'Form Status'
$("#save").attr("disabled",true)
}
ColdFusion.ProgressBar.updateStatus('mycfb',complete,msg)
})
})
added a line that disables the save button if you go back and remove the value from on of the fields. Totally unnecessary for a demo...
http://cf9.coldfusionjedi.com/cfprogressbar/test5....
It doesn't seem any better though. Not that it was bad for me before, but I don't see it updating quicker I mean.
I don't know, maybe I'm just stingy with bandwidth. Does anyone else avoid teh CFAjax features because of the file sizes? Does anyone know a way to reduce the file sizes?
Yes, they are a bit bloated, but they are perfect for in house or small scale application development. I also think that with Ext JS 3.0 the CF9 stuff should speed up a bit more.
The docs don't make this very clear but to use the style attribute just pass in all the options you want to use like this:
style="progresscolor:Blue;bgcolor:Orange;textcolor:Black;"
Though I wouldn't suggest using those colors! ;)
http://cf9.coldfusionjedi.com/cfprogressbar/test2a...
Anyone here took time to see the load behind that !!
http://tools.pingdom.com/fpt/?url=http://cf9.coldf...
1 MB the whole think if the browser load all the stuff !!! For such cosmectifs it's a bit costly !
Regards
M B
As I always say - it's a trade of. EXTREME ease of use over the slimmest performance. For most folks, that 1mg simply won't matter and won't even be noticed.
http://cf9.coldfusionjedi.com/cfprogressbar/test2a...
Example: I have a function in a cfc that interacts with gmail with the cfimap feature. Sometimes the retrieval can be lengthy to say the least I want to use a progressbar to give the user a some type of feedback. Simply enough. How would I measure the total to the total loaded to report back to the progressbar?
Yes. All the examples I see bind to a getStatus function in a cfc. Do I have to place the procedures that I'm trying to do inside that getStatus function? I guess I'm confused on where the loader itself is placed and how the percentages are reported on a resizing or say In my case cfimap progress.
If that makes any sense.
In case someone else gets stuck on this, here's the code I used, after posting the whole CFIDE/scripts/ directory to the "scripts" directory on my site:
<cfajaximport scriptSrc = "http://www.mydomainname.com/scripts/">
Do you mind fixing it so I can review your demo? Thanks!
http://pastebin.com/yPcqgJMt
a) Make the form use Ajax to post it's data.
b) Have the CFM update a shared variable, like a session variable, as it works through it's stuff. So like if it's doing 5 things, it would update a variable like session.status and set it to 1, 2, etc.
c) Use an Ajax polling process to hit a file that simply outputs the value of the session variable. Your client side code would then update the progress bar.
That is leveraging the example on cf10's help on cfprogressbar. Now I just need to make it the actual processing time instead of a generic timed function.
[Add Comment] [Subscribe to Comments]