Ask a Jedi: Cycling through Charts

This post is more than 2 years old.

Alison asks:

Do you have any code for cycling through multiple cfcharts? Basically, I need to see one chart at a time, that changes every few seconds. Any help would be awesome and much appreciated!

I didn't have anything like that handy, but I figured it would be trivial in jQuery. I also assumed that there were probably a few hundred plugins that would do this already, but wanted to see if I could write this myself. Here is what I came up with. Feel free to tear it to bits with suggestions!

First, let's assume you have a block that contains the items you want to cycle through:

<div id="slideshow">

<p>First para</p> <p> Second para </p> <p> Third para </p>

</div>

In this example, I want each paragraph to act like a slide. My code is going to assume that all of the children of the main block are also block level elements.

Ok, so given our HTML, here is the jQuery code I came up with:

<script> var currentPosition = -1 var blocks var lastBlock

$(document).ready(function() {

blocks = $("#slideshow").children()

if(blocks.length) {
	$(blocks).each(function() {
		//hide them
		$(this).hide()
	})
	window.setInterval("showNext()", 2000)
}

})

function showNext() { currentPosition++ if(currentPosition == blocks.length) currentPosition = 0 if(lastBlock) $(lastBlock).fadeOut('normal',function() {$(blocks[currentPosition]).fadeIn() }) else $(blocks[currentPosition]).fadeIn()

lastBlock = blocks[currentPosition]

} </script>

Reading from the top to bottom, I begin with a few global variables that I'll be using throughout the rest of the script. My document.ready block takes care of defining blocks as the children of my div. If I actually have children then I immediately hide them. (If this were for a real site I'd use some CSS to ensure they were hidden initially. Without that you're going to get a 'flash' of content before the script runs.) Next I setup an interval to run showNext.

The showNext function simply increments currentPosition, determines if it needs to hide a previous item and then shows the next one. Pretty simple. You can see this in action here: http://www.coldfusionjedi.com/demos/jan132010/test4a.cfm

Ok, so now let's take it a step further and actually add the charts in. The first thing I noticed is that when the code cycled through the entire set and returned to the beginning, I got the imfamous 'image has expired' issue. That was easy enough to fix by switching to PNG charts, but the quality took a nosedive. You could tweak this a bit - but honestly, I'd just either live with it or try one of the many other charting alternatives there are out there. I also took the opportunity to fix the initial pause. Now my code runs the first slide immediately and then begins the interval. Here is the entire sample with hard coded charts:

<!--- <cfchart format="flash" xaxistitle="Department" yaxistitle="Salary" title="2002"> <cfchartseries type="bar"> <cfchartdata item="Sales" value="90000"> <cfchartdata item="IT" value="20000"> <cfchartdata item="Marketing" value="110000"> </cfchartseries> </cfchart> --->

<html>

<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script> <script> var currentPosition = -1 var blocks var lastBlock

$(document).ready(function() {

blocks = $("#slideshow").children()

if(blocks.length) {
	$(blocks).each(function() {
		//hide them
		$(this).hide()
	})
	showNext()
	window.setInterval("showNext()", 4000)
}

})

function showNext() { currentPosition++ if(currentPosition == blocks.length) currentPosition = 0 if(lastBlock) $(lastBlock).fadeOut('normal',function() {$(blocks[currentPosition]).fadeIn() }) else $(blocks[currentPosition]).fadeIn()

lastBlock = blocks[currentPosition]

} </script> </head>

<body> <h2>Testing</h2>

<div id="slideshow">

<p> <cfchart format="png" xaxistitle="Department" yaxistitle="Salary" title="2002" chartheight="400" chartwidth="400"> <cfchartseries type="bar"> <cfchartdata item="Sales" value="90000"> <cfchartdata item="IT" value="20000"> <cfchartdata item="Marketing" value="110000"> </cfchartseries> </cfchart> </p> <p> <cfchart format="png" xaxistitle="Department" yaxistitle="Salary" title="2003" chartheight="400" chartwidth="400"> <cfchartseries type="bar"> <cfchartdata item="Sales" value="99000"> <cfchartdata item="IT" value="24000"> <cfchartdata item="Marketing" value="120000"> </cfchartseries> </cfchart> </p> <p>

<cfchart format="jpg" xaxistitle="Department" yaxistitle="Salary" title="2004" chartheight="400" chartwidth="400"> <cfchartseries type="bar"> <cfchartdata item="Sales" value="88000"> <cfchartdata item="IT" value="32000"> <cfchartdata item="Marketing" value="100000"> </cfchartseries> </cfchart> </p>

</div>

</body> </html>

You can see this running here: http://www.coldfusionjedi.com/demos/jan132010/test4b.cfm

p.s. I recently got a wishlist item (Dragon America) with a note asking me to contact the person. However, their name was obscured on the packing slip. From time to time I get gifts from my wish list and I can't find a way to contact the person. So if your in that group, accept my apology and thanks!

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Scott P posted on 1/14/2010 at 3:48 AM

Google has a visualization api that will do that. I've got an example of using cf at home that I can post later if anyone is interested.

Google Visualization API
http://code.google.com/apis...

Comment 2 by Raymond Camden posted on 1/14/2010 at 3:49 AM

I reviewed Google Charts for... CFUNITED last year I think. It was a great service, but a royal pain in the ass. I hated how you had to encode data in such a complex manner.

Comment 3 by Raymond Camden posted on 1/14/2010 at 3:57 AM

You know - I take it back. A super quick glance seems to show some pretty nice new stuff there, and _simpler_ stuff at that.

Comment 4 by Andy Sandefer posted on 1/14/2010 at 4:31 AM

@Ray
I really dig this. I'm going to use your nifty slide show technique for an upcoming project (I'll probably throw a pause button and some forward and back controls in but you get the gist). Very cool and easy to understand example - thanks!

Comment 5 by Raymond Camden posted on 1/14/2010 at 4:33 AM

Would you (or other readers) like it if I followed this up with an example that included controls?

Comment 6 by Gary Funk posted on 1/14/2010 at 5:26 AM

Do you even have to ask? Yes. I have a request that I will send you via email.

Comment 7 by todd sharp posted on 1/14/2010 at 6:35 AM

I'd probably have added a class to each 'slide' and just done:

$(".slide-container").hide();

instead of looping over each child like you did.

How 'bout an example that takes each chart and makes each of them a PowerPoint slide with the new PowerPoint ability in CF9 and then calls the SlideSix API and publishes the PowerPoint to SlideSix. Just sayin', that'd rock.... :P

Comment 8 by todd sharp posted on 1/14/2010 at 6:38 AM

Also - in your demo - the first <p> isn't shown right away. Might do something like $('.slide-container:first).show() before calling the setInterval. Or $('.slide-container).not(':first').hide(); (untested)...

Comment 9 by Raymond Camden posted on 1/14/2010 at 7:07 AM

Todd, the issue with the first P not being shown is fixed in the second example. I specifically call out how.

Comment 10 by Tim Brown posted on 1/14/2010 at 8:55 PM

@Scott P - I would love to see your cf and google visualization example. Thanks.

Comment 11 by James Moberg posted on 1/15/2010 at 2:17 AM

Check out the jQuery Cycle Plugin. It is perfect for what you are trying to do and has the ability to add next/prev/pause/resume controls, tabbed navigation, multiple transitions, etc.
http://malsup.com/jquery/cy...

Comment 12 by Michael Kane posted on 9/9/2010 at 1:56 AM

Ray, can you direct me to any material about improving the quality of the charts in JPG or PNG format? I have some projects for which using the cfcharts is required, can't use other products. The relatively poor quality of the JPG/PNG is a problem. Thanks in advance!

Comment 13 by Raymond Camden posted on 9/9/2010 at 2:00 AM

I think you are out of luck. None of the arguments to cfchart allow you to tweak the quality.

Comment 14 by James Moberg posted on 9/9/2010 at 2:09 AM

Michael, I know you stated you can't use other products, but check out ChartDirector. Very customizable and my client preferred the higher quality graphs.
http://www.advsofteng.com/p...