Ask a Jedi: Cycling through Charts

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 developer advocate for Extend by Auth0. He focuses on serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support.

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

Comments